summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:13:15 +0900
committerDongHun Kwak <dh0128.kwak@samsung.com>2021-10-08 09:13:15 +0900
commita9a515dd6b7b96484920a3f0f1202393b91dfd2e (patch)
tree62e21c47bbffdc30a405d1ef04f452ee46a384b6 /Source
parent0375131677cc32a24352f205d05c730690c55af6 (diff)
downloadcmake-a9a515dd6b7b96484920a3f0f1202393b91dfd2e.tar.gz
cmake-a9a515dd6b7b96484920a3f0f1202393b91dfd2e.tar.bz2
cmake-a9a515dd6b7b96484920a3f0f1202393b91dfd2e.zip
Imported Upstream version 3.11.0upstream/3.11.0
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt59
-rw-r--r--Source/CMakeVersion.cmake4
-rw-r--r--Source/CMakeVersion.rc.in37
-rw-r--r--Source/CMakeVersionCompute.cmake10
-rw-r--r--Source/CPack/IFW/cmCPackIFWGenerator.cxx15
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.cxx15
-rw-r--r--Source/CPack/IFW/cmCPackIFWInstaller.h4
-rw-r--r--Source/CPack/WiX/cmCMakeToWixPath.cxx39
-rw-r--r--Source/CPack/WiX/cmCMakeToWixPath.h12
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx41
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.h9
-rw-r--r--Source/CPack/WiX/cmWIXFilesSourceWriter.cxx4
-rw-r--r--Source/CPack/WiX/cmWIXPatchParser.cxx2
-rw-r--r--Source/CPack/bills-comments.txt2
-rw-r--r--Source/CPack/cmCPackArchiveGenerator.cxx11
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx4
-rw-r--r--Source/CPack/cmCPackDragNDropGenerator.cxx27
-rw-r--r--Source/CPack/cmCPackGenerator.cxx101
-rw-r--r--Source/CPack/cmCPackGenerator.h19
-rw-r--r--Source/CPack/cmCPackGeneratorFactory.cxx4
-rw-r--r--Source/CPack/cmCPackNSISGenerator.cxx33
-rw-r--r--Source/CPack/cmCPackOSXX11Generator.cxx7
-rw-r--r--Source/CPack/cmCPackPackageMakerGenerator.cxx10
-rw-r--r--Source/CPack/cmCPackProductBuildGenerator.cxx7
-rw-r--r--Source/CPack/cpack.cxx28
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.cxx123
-rw-r--r--Source/CTest/cmCTestBatchTestHandler.h33
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.cxx47
-rw-r--r--Source/CTest/cmCTestBuildAndTestHandler.h3
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx36
-rw-r--r--Source/CTest/cmCTestBuildHandler.h8
-rw-r--r--Source/CTest/cmCTestConfigureCommand.cxx2
-rw-r--r--Source/CTest/cmCTestConfigureHandler.cxx22
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx79
-rw-r--r--Source/CTest/cmCTestGIT.cxx12
-rw-r--r--Source/CTest/cmCTestLaunch.cxx12
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx69
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.cxx162
-rw-r--r--Source/CTest/cmCTestMultiProcessHandler.h12
-rw-r--r--Source/CTest/cmCTestRunTest.cxx253
-rw-r--r--Source/CTest/cmCTestRunTest.h33
-rw-r--r--Source/CTest/cmCTestSVN.cxx4
-rw-r--r--Source/CTest/cmCTestSVN.h4
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx96
-rw-r--r--Source/CTest/cmCTestScriptHandler.h13
-rw-r--r--Source/CTest/cmCTestStartCommand.cxx2
-rw-r--r--Source/CTest/cmCTestSubmitCommand.cxx2
-rw-r--r--Source/CTest/cmCTestSubmitHandler.cxx59
-rw-r--r--Source/CTest/cmCTestTestCommand.cxx10
-rw-r--r--Source/CTest/cmCTestTestHandler.cxx70
-rw-r--r--Source/CTest/cmCTestTestHandler.h17
-rw-r--r--Source/CTest/cmCTestUpdateHandler.cxx30
-rw-r--r--Source/CTest/cmCTestUploadCommand.cxx2
-rw-r--r--Source/CTest/cmCTestVC.cxx2
-rw-r--r--Source/CTest/cmParseCoberturaCoverage.cxx2
-rw-r--r--Source/CTest/cmParseGTMCoverage.cxx2
-rw-r--r--Source/CTest/cmParseMumpsCoverage.cxx2
-rw-r--r--Source/CTest/cmProcess.cxx736
-rw-r--r--Source/CTest/cmProcess.h94
-rw-r--r--Source/Checks/cm_cxx14_check.cmake36
-rw-r--r--Source/Checks/cm_cxx14_check.cpp (renamed from Source/Checks/cm_cxx14_cstdio.cpp)0
-rw-r--r--Source/Checks/cm_cxx14_cstdio.cmake33
-rw-r--r--Source/Checks/cm_cxx17_check.cmake36
-rw-r--r--Source/Checks/cm_cxx17_check.cpp7
-rw-r--r--Source/Checks/cm_cxx_attribute_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_fallthrough.cxx11
-rw-r--r--Source/Checks/cm_cxx_features.cmake7
-rw-r--r--Source/Checks/cm_cxx_gnu_fallthrough.cxx11
-rw-r--r--Source/CursesDialog/CMakeLists.txt26
-rw-r--r--Source/CursesDialog/ccmake.cxx1
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.cxx21
-rw-r--r--Source/LexerParser/cmCommandArgumentLexer.in.l21
-rw-r--r--Source/Modules/FindLibUUID.cmake85
-rw-r--r--Source/Modules/OverrideC.cmake3
-rw-r--r--Source/Modules/OverrideCXX.cmake3
-rw-r--r--Source/QtDialog/CMakeLists.txt6
-rw-r--r--Source/QtDialog/CMakeSetup.cxx1
-rw-r--r--Source/QtDialog/CMakeSetupDialog.cxx36
-rw-r--r--Source/QtDialog/CMakeSetupDialog.h1
-rw-r--r--Source/QtDialog/QCMake.cxx38
-rw-r--r--Source/QtDialog/QCMake.h8
-rw-r--r--Source/QtDialog/RegexExplorer.cxx4
-rw-r--r--Source/bindexplib.cxx75
-rw-r--r--Source/cmAddCompileOptionsCommand.cxx2
-rw-r--r--Source/cmAddCustomCommandCommand.cxx161
-rw-r--r--Source/cmAddCustomTargetCommand.cxx45
-rw-r--r--Source/cmAddDefinitionsCommand.cxx2
-rw-r--r--Source/cmAddExecutableCommand.cxx57
-rw-r--r--Source/cmAddLibraryCommand.cxx49
-rw-r--r--Source/cmAddSubDirectoryCommand.cxx4
-rw-r--r--Source/cmAlgorithms.h77
-rw-r--r--Source/cmAuxSourceDirectoryCommand.cxx10
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.cxx14
-rw-r--r--Source/cmCMakeHostSystemInformationCommand.h2
-rw-r--r--Source/cmCPluginAPI.cxx8
-rw-r--r--Source/cmCTest.cxx207
-rw-r--r--Source/cmCTest.h44
-rw-r--r--Source/cmCacheManager.cxx80
-rw-r--r--Source/cmCacheManager.h19
-rw-r--r--Source/cmCommandArgumentParserHelper.cxx39
-rw-r--r--Source/cmCommandArgumentParserHelper.h19
-rw-r--r--Source/cmCommands.cxx2
-rw-r--r--Source/cmCommonTargetGenerator.cxx2
-rw-r--r--Source/cmComputeComponentGraph.cxx6
-rw-r--r--Source/cmComputeLinkDepends.cxx7
-rw-r--r--Source/cmComputeLinkInformation.cxx53
-rw-r--r--Source/cmComputeTargetDepends.cxx13
-rw-r--r--Source/cmConditionEvaluator.cxx2
-rw-r--r--Source/cmConfigure.cmake.h.in13
-rw-r--r--Source/cmConfigureFileCommand.cxx2
-rw-r--r--Source/cmConnection.cxx19
-rw-r--r--Source/cmConnection.h5
-rw-r--r--Source/cmConvertMSBuildXMLToJSON.py2
-rw-r--r--Source/cmCoreTryCompile.cxx33
-rw-r--r--Source/cmCoreTryCompile.h2
-rw-r--r--Source/cmCurl.cxx38
-rw-r--r--Source/cmCurl.h2
-rw-r--r--Source/cmCustomCommandGenerator.cxx11
-rw-r--r--Source/cmDependsC.cxx25
-rw-r--r--Source/cmDependsFortran.cxx76
-rw-r--r--Source/cmDependsFortran.h2
-rw-r--r--Source/cmDependsJavaParserHelper.cxx5
-rw-r--r--Source/cmDocumentation.cxx4
-rw-r--r--Source/cmDocumentationSection.cxx6
-rw-r--r--Source/cmDuration.cxx27
-rw-r--r--Source/cmDuration.h24
-rw-r--r--Source/cmELF.cxx3
-rw-r--r--Source/cmExecProgramCommand.cxx4
-rw-r--r--Source/cmExecuteProcessCommand.cxx2
-rw-r--r--Source/cmExpandedCommandArgument.cxx5
-rw-r--r--Source/cmExpandedCommandArgument.h1
-rw-r--r--Source/cmExportBuildAndroidMKGenerator.cxx31
-rw-r--r--Source/cmExportBuildFileGenerator.cxx2
-rw-r--r--Source/cmExportCommand.cxx10
-rw-r--r--Source/cmExportFileGenerator.cxx24
-rw-r--r--Source/cmExportInstallAndroidMKGenerator.h2
-rw-r--r--Source/cmExportInstallFileGenerator.cxx16
-rw-r--r--Source/cmExportTryCompileFileGenerator.cxx19
-rw-r--r--Source/cmExportTryCompileFileGenerator.h5
-rw-r--r--Source/cmExternalMakefileProjectGenerator.cxx7
-rw-r--r--Source/cmExternalMakefileProjectGenerator.h5
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx37
-rw-r--r--Source/cmExtraCodeLiteGenerator.cxx58
-rw-r--r--Source/cmExtraEclipseCDT4Generator.cxx4
-rw-r--r--Source/cmExtraKateGenerator.cxx16
-rw-r--r--Source/cmExtraKateGenerator.h3
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx100
-rw-r--r--Source/cmExtraSublimeTextGenerator.h6
-rw-r--r--Source/cmFSPermissions.cxx34
-rw-r--r--Source/cmFSPermissions.h45
-rw-r--r--Source/cmFileCommand.cxx181
-rw-r--r--Source/cmFilePathChecksum.cxx10
-rw-r--r--Source/cmFilePathChecksum.h4
-rw-r--r--Source/cmFindCommon.cxx4
-rw-r--r--Source/cmFindLibraryCommand.cxx6
-rw-r--r--Source/cmFindPackageCommand.cxx21
-rw-r--r--Source/cmFindPathCommand.cxx4
-rw-r--r--Source/cmFindProgramCommand.cxx2
-rw-r--r--Source/cmForEachCommand.cxx5
-rw-r--r--Source/cmFortranParserImpl.cxx6
-rw-r--r--Source/cmGeneratedFileStream.cxx2
-rw-r--r--Source/cmGeneratorExpression.cxx18
-rw-r--r--Source/cmGeneratorExpression.h85
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx6
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx7
-rw-r--r--Source/cmGeneratorExpressionLexer.cxx22
-rw-r--r--Source/cmGeneratorExpressionNode.cxx40
-rw-r--r--Source/cmGeneratorTarget.cxx77
-rw-r--r--Source/cmGeneratorTarget.h3
-rw-r--r--Source/cmGetDirectoryPropertyCommand.cxx2
-rw-r--r--Source/cmGetPropertyCommand.cxx2
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx10
-rw-r--r--Source/cmGlobalGenerator.cxx393
-rw-r--r--Source/cmGlobalGenerator.h30
-rw-r--r--Source/cmGlobalGhsMultiGenerator.cxx4
-rw-r--r--Source/cmGlobalKdevelopGenerator.cxx589
-rw-r--r--Source/cmGlobalKdevelopGenerator.h81
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx9
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx41
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx17
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h45
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx14
-rw-r--r--Source/cmGlobalVisualStudio11Generator.h16
-rw-r--r--Source/cmGlobalVisualStudio12Generator.h18
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx17
-rw-r--r--Source/cmGlobalVisualStudio14Generator.h16
-rw-r--r--Source/cmGlobalVisualStudio15Generator.cxx47
-rw-r--r--Source/cmGlobalVisualStudio15Generator.h17
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx37
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h27
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx111
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h40
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx67
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h44
-rw-r--r--Source/cmGlobalVisualStudio9Generator.cxx6
-rw-r--r--Source/cmGlobalVisualStudio9Generator.h8
-rw-r--r--Source/cmGlobalVisualStudioGenerator.cxx151
-rw-r--r--Source/cmGlobalVisualStudioGenerator.h15
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx546
-rw-r--r--Source/cmGlobalXCodeGenerator.h13
-rw-r--r--Source/cmGraphVizWriter.cxx4
-rw-r--r--Source/cmIDEOptions.cxx57
-rw-r--r--Source/cmIDEOptions.h20
-rw-r--r--Source/cmIncludeCommand.cxx4
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx8
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx5
-rw-r--r--Source/cmInstallCommand.cxx15
-rw-r--r--Source/cmInstallCommandArguments.cxx4
-rw-r--r--Source/cmInstallDirectoryGenerator.cxx2
-rw-r--r--Source/cmInstallExportGenerator.cxx2
-rw-r--r--Source/cmInstallFilesCommand.cxx7
-rw-r--r--Source/cmInstallGenerator.cxx4
-rw-r--r--Source/cmInstallProgramsCommand.cxx4
-rw-r--r--Source/cmInstallTargetGenerator.cxx28
-rw-r--r--Source/cmLinkDirectoriesCommand.cxx2
-rw-r--r--Source/cmLinkedTree.h6
-rw-r--r--Source/cmListFileCache.cxx16
-rw-r--r--Source/cmListFileCache.h4
-rw-r--r--Source/cmLoadCacheCommand.cxx2
-rw-r--r--Source/cmLocalCommonGenerator.cxx15
-rw-r--r--Source/cmLocalCommonGenerator.h6
-rw-r--r--Source/cmLocalGenerator.cxx191
-rw-r--r--Source/cmLocalGenerator.h51
-rw-r--r--Source/cmLocalNinjaGenerator.cxx17
-rw-r--r--Source/cmLocalNinjaGenerator.h5
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx89
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h13
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx14
-rw-r--r--Source/cmLocalVisualStudio10Generator.h10
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx291
-rw-r--r--Source/cmLocalVisualStudio7Generator.h16
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx14
-rw-r--r--Source/cmLocalVisualStudioGenerator.h6
-rw-r--r--Source/cmLocalXCodeGenerator.cxx12
-rw-r--r--Source/cmLocalXCodeGenerator.h2
-rw-r--r--Source/cmMacroCommand.cxx3
-rw-r--r--Source/cmMakeDirectoryCommand.cxx4
-rw-r--r--Source/cmMakefile.cxx466
-rw-r--r--Source/cmMakefile.h99
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx17
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx23
-rw-r--r--Source/cmMakefileTargetGenerator.cxx182
-rw-r--r--Source/cmMakefileTargetGenerator.h3
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx11
-rw-r--r--Source/cmMessageCommand.cxx2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx35
-rw-r--r--Source/cmNinjaTargetGenerator.cxx96
-rw-r--r--Source/cmNinjaTargetGenerator.h3
-rw-r--r--Source/cmOSXBundleGenerator.cxx14
-rw-r--r--Source/cmOrderDirectories.cxx2
-rw-r--r--Source/cmOutputConverter.cxx4
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx22
-rw-r--r--Source/cmParseArgumentsCommand.cxx26
-rw-r--r--Source/cmPipeConnection.cxx51
-rw-r--r--Source/cmPipeConnection.h4
-rw-r--r--Source/cmPolicies.h6
-rw-r--r--Source/cmProcessOutput.cxx2
-rw-r--r--Source/cmProjectCommand.cxx2
-rw-r--r--Source/cmQTWrapCPPCommand.cxx6
-rw-r--r--Source/cmQTWrapUICommand.cxx10
-rw-r--r--Source/cmQtAutoGen.cxx333
-rw-r--r--Source/cmQtAutoGen.h54
-rw-r--r--Source/cmQtAutoGenDigest.h64
-rw-r--r--Source/cmQtAutoGenInitializer.cxx1393
-rw-r--r--Source/cmQtAutoGenInitializer.h115
-rw-r--r--Source/cmQtAutoGenerator.cxx641
-rw-r--r--Source/cmQtAutoGenerator.h252
-rw-r--r--Source/cmQtAutoGeneratorInitializer.cxx1236
-rw-r--r--Source/cmQtAutoGeneratorInitializer.h24
-rw-r--r--Source/cmQtAutoGeneratorMocUic.cxx2028
-rw-r--r--Source/cmQtAutoGeneratorMocUic.h438
-rw-r--r--Source/cmQtAutoGeneratorRcc.cxx638
-rw-r--r--Source/cmQtAutoGeneratorRcc.h103
-rw-r--r--Source/cmQtAutoGenerators.cxx2341
-rw-r--r--Source/cmQtAutoGenerators.h248
-rw-r--r--Source/cmRemoveDefinitionsCommand.cxx2
-rw-r--r--Source/cmSearchPath.cxx4
-rw-r--r--Source/cmServer.cxx101
-rw-r--r--Source/cmServer.h13
-rw-r--r--Source/cmServerConnection.cxx71
-rw-r--r--Source/cmServerConnection.h6
-rw-r--r--Source/cmServerDictionary.h8
-rw-r--r--Source/cmServerProtocol.cxx268
-rw-r--r--Source/cmServerProtocol.h1
-rw-r--r--Source/cmSetCommand.cxx14
-rw-r--r--Source/cmSetPropertyCommand.cxx2
-rw-r--r--Source/cmSourceFile.cxx9
-rw-r--r--Source/cmSourceFile.h8
-rw-r--r--Source/cmSourceFileLocation.cxx36
-rw-r--r--Source/cmSourceFileLocation.h10
-rw-r--r--Source/cmSourceFileLocationKind.h15
-rw-r--r--Source/cmSourceGroup.cxx57
-rw-r--r--Source/cmSourceGroup.h16
-rw-r--r--Source/cmSourceGroupCommand.cxx228
-rw-r--r--Source/cmSourceGroupCommand.h23
-rw-r--r--Source/cmStandardLexer.h2
-rw-r--r--Source/cmState.cxx14
-rw-r--r--Source/cmState.h7
-rw-r--r--Source/cmStateSnapshot.cxx6
-rw-r--r--Source/cmSystemTools.cxx116
-rw-r--r--Source/cmSystemTools.h27
-rw-r--r--Source/cmTarget.cxx116
-rw-r--r--Source/cmTarget.h7
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx13
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.h1
-rw-r--r--Source/cmTargetCompileFeaturesCommand.cxx13
-rw-r--r--Source/cmTargetCompileFeaturesCommand.h1
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx13
-rw-r--r--Source/cmTargetCompileOptionsCommand.h1
-rw-r--r--Source/cmTargetDepend.h2
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.cxx18
-rw-r--r--Source/cmTargetIncludeDirectoriesCommand.h1
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx207
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h3
-rw-r--r--Source/cmTargetPropCommandBase.cxx15
-rw-r--r--Source/cmTargetPropCommandBase.h1
-rw-r--r--Source/cmTargetPropertyComputer.cxx8
-rw-r--r--Source/cmTargetSourcesCommand.cxx9
-rw-r--r--Source/cmTargetSourcesCommand.h1
-rw-r--r--Source/cmTestGenerator.cxx10
-rw-r--r--Source/cmTestGenerator.h5
-rw-r--r--Source/cmTimestamp.cxx8
-rw-r--r--Source/cmTryCompileCommand.cxx2
-rw-r--r--Source/cmTryRunCommand.cxx15
-rw-r--r--Source/cmUVHandlePtr.cxx227
-rw-r--r--Source/cmUVHandlePtr.h222
-rw-r--r--Source/cmUVSignalHackRAII.h44
-rw-r--r--Source/cmUnsetCommand.cxx13
-rw-r--r--Source/cmUseMangledMesaCommand.cxx6
-rw-r--r--Source/cmUtilitySourceCommand.cxx4
-rw-r--r--Source/cmUtils.hxx2
-rw-r--r--Source/cmVS141CLFlagTable.h4
-rw-r--r--Source/cmVSSetupHelper.cxx36
-rw-r--r--Source/cmVSSetupHelper.h4
-rw-r--r--Source/cmVariableWatchCommand.cxx18
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx822
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h28
-rw-r--r--Source/cmVisualStudioGeneratorOptions.cxx120
-rw-r--r--Source/cmVisualStudioGeneratorOptions.h4
-rw-r--r--Source/cmWriteFileCommand.cxx4
-rw-r--r--Source/cmXCodeObject.cxx26
-rw-r--r--Source/cmXCodeObject.h2
-rw-r--r--Source/cmXMLWriter.h18
-rw-r--r--Source/cm_codecvt.cxx14
-rw-r--r--Source/cm_thread.hxx44
-rw-r--r--Source/cmake.cxx201
-rw-r--r--Source/cmake.h33
-rw-r--r--Source/cmakemain.cxx60
-rw-r--r--Source/cmakexbuild.cxx7
-rw-r--r--Source/cmcmd.cxx65
-rw-r--r--Source/ctest.cxx3
-rw-r--r--Source/kwsys/CMakeLists.txt87
-rw-r--r--Source/kwsys/CommandLineArguments.cxx47
-rw-r--r--Source/kwsys/Configure.h.in3
-rw-r--r--Source/kwsys/Configure.hxx.in33
-rw-r--r--Source/kwsys/ConsoleBuf.hxx.in2
-rw-r--r--Source/kwsys/Directory.cxx2
-rw-r--r--Source/kwsys/DynamicLoader.cxx19
-rw-r--r--Source/kwsys/DynamicLoader.hxx.in4
-rw-r--r--Source/kwsys/EncodingCXX.cxx12
-rw-r--r--Source/kwsys/Glob.cxx10
-rw-r--r--Source/kwsys/Process.h.in10
-rw-r--r--Source/kwsys/ProcessUNIX.c35
-rw-r--r--Source/kwsys/ProcessWin32.c20
-rw-r--r--Source/kwsys/RegularExpression.cxx313
-rw-r--r--Source/kwsys/RegularExpression.hxx.in233
-rw-r--r--Source/kwsys/SharedForward.h.in2
-rw-r--r--Source/kwsys/SystemInformation.cxx151
-rw-r--r--Source/kwsys/SystemInformation.hxx.in6
-rw-r--r--Source/kwsys/SystemTools.cxx242
-rw-r--r--Source/kwsys/SystemTools.hxx.in27
-rw-r--r--Source/kwsys/hash_map.hxx.in2
-rw-r--r--Source/kwsys/hash_set.hxx.in2
-rw-r--r--Source/kwsys/hashtable.hxx.in13
-rw-r--r--Source/kwsys/kwsysPlatformTestsC.c15
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx2
-rw-r--r--Source/kwsys/testCommandLineArguments.cxx4
-rw-r--r--Source/kwsys/testCommandLineArguments1.cxx6
-rw-r--r--Source/kwsys/testConfigure.cxx30
-rw-r--r--Source/kwsys/testEncoding.cxx9
-rw-r--r--Source/kwsys/testProcess.c32
-rw-r--r--Source/kwsys/testSystemTools.cxx98
383 files changed, 14416 insertions, 10203 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index a4dd91860..a0010a292 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -216,6 +216,8 @@ set(SRCS
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmFortranParserImpl.cxx
+ cmFSPermissions.cxx
+ cmFSPermissions.h
cmGeneratedFileStream.cxx
cmGeneratorExpressionContext.cxx
cmGeneratorExpressionContext.h
@@ -309,11 +311,14 @@ set(SRCS
cmPropertyMap.h
cmQtAutoGen.cxx
cmQtAutoGen.h
- cmQtAutoGenDigest.h
- cmQtAutoGeneratorInitializer.cxx
- cmQtAutoGeneratorInitializer.h
- cmQtAutoGenerators.cxx
- cmQtAutoGenerators.h
+ cmQtAutoGenerator.cxx
+ cmQtAutoGenerator.h
+ cmQtAutoGenInitializer.cxx
+ cmQtAutoGenInitializer.h
+ cmQtAutoGeneratorMocUic.cxx
+ cmQtAutoGeneratorMocUic.h
+ cmQtAutoGeneratorRcc.cxx
+ cmQtAutoGeneratorRcc.h
cmRST.cxx
cmRST.h
cmScriptGenerator.h
@@ -322,6 +327,7 @@ set(SRCS
cmSourceFile.h
cmSourceFileLocation.cxx
cmSourceFileLocation.h
+ cmSourceFileLocationKind.h
cmSourceGroup.cxx
cmSourceGroup.h
cmState.cxx
@@ -343,6 +349,9 @@ set(SRCS
cmTestGenerator.cxx
cmTestGenerator.h
cmUuid.cxx
+ cmUVHandlePtr.cxx
+ cmUVHandlePtr.h
+ cmUVSignalHackRAII.h
cmVariableWatch.cxx
cmVariableWatch.h
cmVersion.cxx
@@ -593,16 +602,15 @@ set(SRCS
cm_utf8.c
cm_codecvt.hxx
cm_codecvt.cxx
+ cm_thread.hxx
+
+ cmDuration.h
+ cmDuration.cxx
)
SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS
KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
-# Kdevelop only works on UNIX and not windows
-if(UNIX)
- set(SRCS ${SRCS} cmGlobalKdevelopGenerator.cxx)
-endif()
-
# Xcode only works on Apple
if(APPLE)
set(SRCS ${SRCS}
@@ -757,6 +765,7 @@ target_link_libraries(CMakeLib cmsys
${CMAKE_LIBUV_LIBRARIES}
${CMAKE_LIBRHASH_LIBRARIES}
${CMake_KWIML_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
@@ -794,7 +803,6 @@ include_directories(
#
set(CTEST_SRCS cmCTest.cxx
CTest/cmProcess.cxx
- CTest/cmCTestBatchTestHandler.cxx
CTest/cmCTestBuildAndTestHandler.cxx
CTest/cmCTestBuildCommand.cxx
CTest/cmCTestBuildHandler.cxx
@@ -915,7 +923,7 @@ if(UNIX)
# OpenBSD and also Linux and OSX. Look for the header and
# the library; it's a warning on FreeBSD if they're not
# found, and informational on other platforms.
- find_path(FREEBSD_PKG_INCLUDE_DIRS "pkg.h" PATHS /usr/local)
+ find_path(FREEBSD_PKG_INCLUDE_DIRS "pkg.h")
if(FREEBSD_PKG_INCLUDE_DIRS)
find_library(FREEBSD_PKG_LIBRARIES
pkg
@@ -936,8 +944,13 @@ if(UNIX)
endif()
endif()
-if(WIN32)
+if(CYGWIN)
+ find_package(LibUUID)
+endif()
+if(WIN32 OR (CYGWIN AND LibUUID_FOUND))
set(CPACK_SRCS ${CPACK_SRCS}
+ CPack/Wix/cmCMakeToWixPath.cxx
+ CPack/Wix/cmCMakeToWixPath.h
CPack/WiX/cmCPackWIXGenerator.cxx
CPack/WiX/cmCPackWIXGenerator.h
CPack/WiX/cmWIXAccessControlList.cxx
@@ -958,7 +971,7 @@ if(WIN32)
CPack/WiX/cmWIXShortcut.h
CPack/WiX/cmWIXSourceWriter.cxx
CPack/WiX/cmWIXSourceWriter.h
- )
+ )
endif()
if(APPLE)
@@ -991,6 +1004,11 @@ if(APPLE)
"See CMakeFiles/CMakeError.log for details of the failure.")
endif()
endif()
+if(CYGWIN AND LibUUID_FOUND)
+ target_link_libraries(CPackLib ${LibUUID_LIBRARIES})
+ include_directories(CPackLib ${LibUUID_INCLUDE_DIRS})
+ set_property(SOURCE CPack/cmCPackGeneratorFactory.cxx PROPERTY COMPILE_DEFINITIONS HAVE_LIBUUID)
+endif()
if(CPACK_ENABLE_FREEBSD_PKG AND FREEBSD_PKG_INCLUDE_DIRS AND FREEBSD_PKG_LIBRARIES)
target_link_libraries(CPackLib ${FREEBSD_PKG_LIBRARIES})
include_directories(${FREEBSD_PKG_INCLUDE_DIRS})
@@ -1047,6 +1065,19 @@ endif()
include (${CMake_BINARY_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
include (${CMake_SOURCE_DIR}/Source/LocalUserOptions.cmake OPTIONAL)
+if(WIN32)
+ # Add Windows executable version information.
+ configure_file("CMakeVersion.rc.in" "CMakeVersion.rc" @ONLY)
+
+ # We use a separate object library for this to work around a limitation of
+ # MinGW's windres tool with spaces in the path to the include directories.
+ add_library(CMakeVersion OBJECT "${CMAKE_CURRENT_BINARY_DIR}/CMakeVersion.rc")
+ set_property(TARGET CMakeVersion PROPERTY INCLUDE_DIRECTORIES "")
+ foreach(_tool ${_tools})
+ target_sources(${_tool} PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
+ endforeach()
+endif()
+
# Install tools
foreach(_tool ${_tools})
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 9367e480f..533d59fec 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 3)
+set(CMake_VERSION_MINOR 11)
+set(CMake_VERSION_PATCH 0)
#set(CMake_VERSION_RC 0)
diff --git a/Source/CMakeVersion.rc.in b/Source/CMakeVersion.rc.in
new file mode 100644
index 000000000..22b4a3639
--- /dev/null
+++ b/Source/CMakeVersion.rc.in
@@ -0,0 +1,37 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+
+#define VER_FILEVERSION @CMake_RCVERSION@
+#define VER_FILEVERSION_STR "@CMake_RCVERSION_STR@\0"
+
+#define VER_PRODUCTVERSION @CMake_RCVERSION@
+#define VER_PRODUCTVERSION_STR "@CMake_RCVERSION_STR@\0"
+
+/* Version-information resource identifier. */
+#define VS_VERSION_INFO 1
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION VER_FILEVERSION
+PRODUCTVERSION VER_PRODUCTVERSION
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904E4"
+ BEGIN
+ VALUE "FileVersion", VER_FILEVERSION_STR
+ VALUE "ProductVersion", VER_PRODUCTVERSION_STR
+ END
+ END
+
+ BLOCK "VarFileInfo"
+ BEGIN
+ /* The following line should only be modified for localized versions. */
+ /* It consists of any number of WORD,WORD pairs, with each pair */
+ /* describing a language,codepage combination supported by the file. */
+ /* */
+ /* For example, a file might have values "0x409,1252" indicating that it */
+ /* supports English language (0x409) in the Windows ANSI codepage (1252). */
+
+ VALUE "Translation", 0x409, 1252
+ END
+END
diff --git a/Source/CMakeVersionCompute.cmake b/Source/CMakeVersionCompute.cmake
index d9218d731..79264ed37 100644
--- a/Source/CMakeVersionCompute.cmake
+++ b/Source/CMakeVersionCompute.cmake
@@ -27,3 +27,13 @@ endif()
if(CMake_VERSION_IS_DIRTY)
set(CMake_VERSION ${CMake_VERSION}-dirty)
endif()
+
+# Compute the binary version that appears in the RC file. Version
+# components in the RC file are 16-bit integers so we may have to
+# split the patch component.
+if(CMake_VERSION_PATCH MATCHES "^([0-9]+)([0-9][0-9][0-9][0-9])$")
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMAKE_MATCH_1},${CMAKE_MATCH_2})
+else()
+ set(CMake_RCVERSION ${CMake_VERSION_MAJOR},${CMake_VERSION_MINOR},${CMake_VERSION_PATCH})
+endif()
+set(CMake_RCVERSION_STR ${CMake_VERSION})
diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index 825a88804..9f1a15e25 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -9,6 +9,7 @@
#include "cmCPackIFWPackage.h"
#include "cmCPackIFWRepository.h"
#include "cmCPackLog.h" // IWYU pragma: keep
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
@@ -61,7 +62,7 @@ int cmCPackIFWGenerator::PackageFiles()
}
} else {
cmCPackIFWLogger(WARNING, "The \"CPACK_IFW_REPOSITORIES_DIRECTORIES\" "
- << "variable is set, but content will be skiped, "
+ << "variable is set, but content will be skipped, "
<< "because this feature available only since "
<< "QtIFW 3.1. Please update your QtIFW instance."
<< std::endl);
@@ -84,9 +85,9 @@ int cmCPackIFWGenerator::PackageFiles()
std::string output;
int retVal = 1;
cmCPackIFWLogger(OUTPUT, "- Generate repository" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
- &output, &retVal, nullptr,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ ifwCmd.c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
cmGeneratedFileStream ofs(ifwTmpFile.c_str());
ofs << "# Run command: " << ifwCmd << std::endl
@@ -194,9 +195,9 @@ int cmCPackIFWGenerator::PackageFiles()
std::string output;
int retVal = 1;
cmCPackIFWLogger(OUTPUT, "- Generate package" << std::endl);
- bool res = cmSystemTools::RunSingleCommand(ifwCmd.c_str(), &output,
- &output, &retVal, nullptr,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ ifwCmd.c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
cmGeneratedFileStream ofs(ifwTmpFile.c_str());
ofs << "# Run command: " << ifwCmd << std::endl
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 422f5d5e7..05a852d1d 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -93,6 +93,15 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
}
}
+ // RemoveTargetDir
+ if (this->IsSetToOff("CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR")) {
+ this->RemoveTargetDir = "false";
+ } else if (this->IsOn("CPACK_IFW_PACKAGE_REMOVE_TARGET_DIR")) {
+ this->RemoveTargetDir = "true";
+ } else {
+ this->RemoveTargetDir.clear();
+ }
+
// Logo
if (const char* option = this->GetOption("CPACK_IFW_PACKAGE_LOGO")) {
if (cmSystemTools::FileExists(option)) {
@@ -422,6 +431,10 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
xout.Element("MaintenanceToolIniFile", this->MaintenanceToolIniFile);
}
+ if (!this->RemoveTargetDir.empty()) {
+ xout.Element("RemoveTargetDir", this->RemoveTargetDir);
+ }
+
// Different allows
if (this->IsVersionLess("2.0")) {
// CPack IFW default policy
@@ -454,7 +467,7 @@ void cmCPackIFWInstaller::GenerateInstallerFile()
std::string name = cmSystemTools::GetFilenameName(this->Resources[i]);
std::string path = this->Directory + "/resources/" + name;
cmsys::SystemTools::CopyFileIfDifferent(this->Resources[i], path);
- resources.push_back(name);
+ resources.push_back(std::move(name));
} else {
cmCPackIFWLogger(WARNING, "Can't copy resources from \""
<< this->Resources[i]
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h
index b635f4222..37ad339af 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.h
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.h
@@ -99,6 +99,10 @@ public:
/// Set to true if the installation path can contain non-ASCII characters
std::string AllowNonAsciiCharacters;
+ /// Set to false if the target directory should not be deleted when
+ /// uninstalling
+ std::string RemoveTargetDir;
+
/// Set to false if the installation path cannot contain space characters
std::string AllowSpaceInPath;
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.cxx b/Source/CPack/WiX/cmCMakeToWixPath.cxx
new file mode 100644
index 000000000..0b0e42aa9
--- /dev/null
+++ b/Source/CPack/WiX/cmCMakeToWixPath.cxx
@@ -0,0 +1,39 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmCMakeToWixPath.h"
+
+#include "cmSystemTools.h"
+
+#include <string>
+#include <vector>
+
+#ifdef __CYGWIN__
+#include <sys/cygwin.h>
+std::string CMakeToWixPath(const std::string& cygpath)
+{
+ std::vector<char> winpath_chars;
+ ssize_t winpath_size;
+
+ // Get the required buffer size.
+ winpath_size =
+ cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(), nullptr, 0);
+ if (winpath_size <= 0) {
+ return cygpath;
+ }
+
+ winpath_chars.assign(static_cast<size_t>(winpath_size) + 1, '\0');
+
+ winpath_size = cygwin_conv_path(CCP_POSIX_TO_WIN_A, cygpath.c_str(),
+ winpath_chars.data(), winpath_size);
+ if (winpath_size < 0) {
+ return cygpath;
+ }
+
+ return cmSystemTools::TrimWhitespace(winpath_chars.data());
+}
+#else
+std::string CMakeToWixPath(const std::string& path)
+{
+ return path;
+}
+#endif
diff --git a/Source/CPack/WiX/cmCMakeToWixPath.h b/Source/CPack/WiX/cmCMakeToWixPath.h
new file mode 100644
index 000000000..8bb9e0408
--- /dev/null
+++ b/Source/CPack/WiX/cmCMakeToWixPath.h
@@ -0,0 +1,12 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmCMakeToWixPath_h
+#define cmCMakeToWixPath_h
+
+#include "cmConfigure.h" //IWYU pragma: keep
+
+#include <string>
+
+std::string CMakeToWixPath(const std::string& cygpath);
+
+#endif // cmCMakeToWixPath_h
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index ba07d0863..a0bc0eabd 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -22,7 +22,13 @@
#include "cmsys/FStream.hxx"
#include "cmsys/SystemTools.hxx"
-#include <rpc.h> // for GUID generation
+#ifdef _WIN32
+#include <rpc.h> // for GUID generation (windows only)
+#else
+#include <uuid/uuid.h> // for GUID generation (libuuid)
+#endif
+
+#include "cmCMakeToWixPath.h"
cmCPackWIXGenerator::cmCPackWIXGenerator()
: Patch(0)
@@ -110,7 +116,7 @@ bool cmCPackWIXGenerator::RunLightCommand(std::string const& objectFiles)
std::ostringstream command;
command << QuotePath(executable);
command << " -nologo";
- command << " -out " << QuotePath(packageFileNames.at(0));
+ command << " -out " << QuotePath(CMakeToWixPath(packageFileNames.at(0)));
for (std::string const& ext : this->LightExtensions) {
command << " -ext " << QuotePath(ext);
@@ -270,11 +276,12 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
std::string objectFilename =
this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj";
- if (!RunCandleCommand(sourceFilename, objectFilename)) {
+ if (!RunCandleCommand(CMakeToWixPath(sourceFilename),
+ CMakeToWixPath(objectFilename))) {
return false;
}
- objectFiles << " " << QuotePath(objectFilename);
+ objectFiles << " " << QuotePath(CMakeToWixPath(objectFilename));
}
AppendUserSuppliedExtraObjects(objectFiles);
@@ -320,10 +327,10 @@ void cmCPackWIXGenerator::CreateWiXVariablesIncludeFile()
CopyDefinition(includeFile, "CPACK_PACKAGE_VENDOR");
CopyDefinition(includeFile, "CPACK_PACKAGE_NAME");
CopyDefinition(includeFile, "CPACK_PACKAGE_VERSION");
- CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF");
- CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON");
- CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER");
- CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG");
+ CopyDefinition(includeFile, "CPACK_WIX_LICENSE_RTF", DefinitionType::PATH);
+ CopyDefinition(includeFile, "CPACK_WIX_PRODUCT_ICON", DefinitionType::PATH);
+ CopyDefinition(includeFile, "CPACK_WIX_UI_BANNER", DefinitionType::PATH);
+ CopyDefinition(includeFile, "CPACK_WIX_UI_DIALOG", DefinitionType::PATH);
SetOptionIfNotSet("CPACK_WIX_PROGRAM_MENU_FOLDER",
GetOption("CPACK_PACKAGE_NAME"));
CopyDefinition(includeFile, "CPACK_WIX_PROGRAM_MENU_FOLDER");
@@ -390,11 +397,16 @@ void cmCPackWIXGenerator::CreateWiXProductFragmentIncludeFile()
}
void cmCPackWIXGenerator::CopyDefinition(cmWIXSourceWriter& source,
- std::string const& name)
+ std::string const& name,
+ DefinitionType type)
{
const char* value = GetOption(name.c_str());
if (value) {
- AddDefinition(source, name, value);
+ if (type == DefinitionType::PATH) {
+ AddDefinition(source, name, CMakeToWixPath(value));
+ } else {
+ AddDefinition(source, name, value);
+ }
}
}
@@ -966,6 +978,7 @@ std::string cmCPackWIXGenerator::GetArchitecture() const
std::string cmCPackWIXGenerator::GenerateGUID()
{
+#ifdef _WIN32
UUID guid;
UuidCreate(&guid);
@@ -975,6 +988,14 @@ std::string cmCPackWIXGenerator::GenerateGUID()
std::string result =
cmsys::Encoding::ToNarrow(reinterpret_cast<wchar_t*>(tmp));
RpcStringFreeW(&tmp);
+#else
+ uuid_t guid;
+ char guid_ch[37] = { 0 };
+
+ uuid_generate(guid);
+ uuid_unparse(guid, guid_ch);
+ std::string result = guid_ch;
+#endif
return cmSystemTools::UpperCase(result);
}
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.h b/Source/CPack/WiX/cmCPackWIXGenerator.h
index b2633a7f9..128a04de8 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.h
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.h
@@ -48,6 +48,12 @@ private:
typedef std::map<std::string, size_t> ambiguity_map_t;
typedef std::set<std::string> extension_set_t;
+ enum class DefinitionType
+ {
+ STRING,
+ PATH
+ };
+
bool InitializeWiXConfiguration();
bool PackageFilesImpl();
@@ -58,7 +64,8 @@ private:
void CreateWiXProductFragmentIncludeFile();
- void CopyDefinition(cmWIXSourceWriter& source, std::string const& name);
+ void CopyDefinition(cmWIXSourceWriter& source, std::string const& name,
+ DefinitionType type = DefinitionType::STRING);
void AddDefinition(cmWIXSourceWriter& source, std::string const& name,
std::string const& value);
diff --git a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
index b4cd1a3d6..dd3caf9d3 100644
--- a/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
+++ b/Source/CPack/WiX/cmWIXFilesSourceWriter.cxx
@@ -11,6 +11,8 @@
#include "cm_sys_stat.h"
+#include "cmCMakeToWixPath.h"
+
cmWIXFilesSourceWriter::cmWIXFilesSourceWriter(cmCPackLog* logger,
std::string const& filename,
GuidType componentGuidType)
@@ -139,7 +141,7 @@ std::string cmWIXFilesSourceWriter::EmitComponentFile(
patch.ApplyFragment(componentId, *this);
BeginElement("File");
AddAttribute("Id", fileId);
- AddAttribute("Source", filePath);
+ AddAttribute("Source", CMakeToWixPath(filePath));
AddAttribute("KeyPath", "yes");
mode_t fileMode = 0;
diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx
index e6aeed325..c6ca9441a 100644
--- a/Source/CPack/WiX/cmWIXPatchParser.cxx
+++ b/Source/CPack/WiX/cmWIXPatchParser.cxx
@@ -90,7 +90,7 @@ void cmWIXPatchParser::StartFragment(const char** attributes)
}
}
- /* add any additional attributes for the fragement */
+ /* add any additional attributes for the fragment */
if (!new_element) {
ReportValidationError("No 'Id' specified for 'CPackWixFragment' element");
} else {
diff --git a/Source/CPack/bills-comments.txt b/Source/CPack/bills-comments.txt
index c3b4ee8e7..1aaf9af51 100644
--- a/Source/CPack/bills-comments.txt
+++ b/Source/CPack/bills-comments.txt
@@ -31,7 +31,7 @@ cmCPackGenericGenerator::ProcessGenerator // DoPackage
cmCPackGenericGenerator::InstallProject is used for both source and binary
-packages. It is controled based on values set in CPACK_ variables.
+packages. It is controlled based on values set in CPACK_ variables.
InstallProject
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 641be3861..9ff547a49 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -132,7 +132,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
}
}
// add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
}
// Handle Orphan components (components not belonging to any groups)
for (auto& comp : this->Components) {
@@ -157,7 +157,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
addOneComponentToArchive(archive, &(comp.second));
}
// add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
}
}
}
@@ -178,7 +178,7 @@ int cmCPackArchiveGenerator::PackageComponents(bool ignoreGroup)
addOneComponentToArchive(archive, &(comp.second));
}
// add the generated package to package file names list
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
}
}
return 1;
@@ -188,7 +188,7 @@ int cmCPackArchiveGenerator::PackageComponentsAllInOne()
{
// reset the package file names
packageFileNames.clear();
- packageFileNames.push_back(std::string(toplevel));
+ packageFileNames.emplace_back(toplevel);
packageFileNames[0] += "/";
if (this->IsSet("CPACK_ARCHIVE_FILE_NAME")) {
@@ -239,8 +239,7 @@ int cmCPackArchiveGenerator::PackageFiles()
cmWorkingDirectory workdir(toplevel);
for (std::string const& file : files) {
// Get the relative path to the file
- std::string rp =
- cmSystemTools::RelativePath(toplevel.c_str(), file.c_str());
+ std::string rp = cmSystemTools::RelativePath(toplevel, file);
archive.Add(rp, 0, nullptr, false);
if (!archive) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem while adding file< "
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 7fc3c26de..8ec54f88e 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -89,7 +89,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
packageFileName += "/";
packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
return retval;
}
@@ -206,7 +206,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
packageFileName += "/";
packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
- packageFileNames.push_back(packageFileName);
+ packageFileNames.push_back(std::move(packageFileName));
return retval;
}
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 1e1543f9d..e95b96dfe 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -4,6 +4,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
@@ -242,9 +243,9 @@ bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
{
int exit_code = 1;
- bool result = cmSystemTools::RunSingleCommand(command.str().c_str(), output,
- output, &exit_code, nullptr,
- this->GeneratorVerbose, 0);
+ bool result = cmSystemTools::RunSingleCommand(
+ command.str().c_str(), output, output, &exit_code, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (!result || exit_code) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Error executing: " << command.str()
@@ -411,6 +412,7 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
temp_image += "/temp.dmg";
+ std::string create_error;
std::ostringstream temp_image_command;
temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
temp_image_command << " create";
@@ -421,9 +423,11 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
temp_image_command << " -format " << temp_image_format;
temp_image_command << " \"" << temp_image << "\"";
- if (!this->RunCommand(temp_image_command)) {
+ if (!this->RunCommand(temp_image_command, &create_error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
- "Error generating temporary disk image." << std::endl);
+ "Error generating temporary disk image." << std::endl
+ << create_error
+ << std::endl);
return 0;
}
@@ -464,15 +468,17 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
// Optionally set the custom icon flag for the image ...
if (!had_error && !cpack_package_icon.empty()) {
+ std::string error;
std::ostringstream setfile_command;
setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
setfile_command << " -a C";
setfile_command << " \"" << temp_mount << "\"";
- if (!this->RunCommand(setfile_command)) {
+ if (!this->RunCommand(setfile_command, &error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Error assigning custom icon to temporary disk image."
- << std::endl);
+ << std::endl
+ << error << std::endl);
had_error = true;
}
@@ -717,9 +723,12 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
final_image_command << " zlib-level=9";
final_image_command << " -o \"" << output_file << "\"";
- if (!this->RunCommand(final_image_command)) {
+ std::string convert_error;
+
+ if (!this->RunCommand(final_image_command, &convert_error)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Error compressing disk image."
- << std::endl);
+ << std::endl
+ << convert_error << std::endl);
return 0;
}
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index ecb5adb47..d838b301f 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -12,10 +12,13 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
#include "cmCryptoHash.h"
+#include "cmDuration.h"
+#include "cmFSPermissions.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateSnapshot.h"
+#include "cmVersion.h"
#include "cmWorkingDirectory.h"
#include "cmXMLSafe.h"
#include "cmake.h"
@@ -184,7 +187,7 @@ int cmCPackGenerator::InstallProject()
const char* tempInstallDirectory = tempInstallDirectoryStr.c_str();
int res = 1;
- if (!cmsys::SystemTools::MakeDirectory(bareTempInstallDirectory.c_str())) {
+ if (!cmsys::SystemTools::MakeDirectory(bareTempInstallDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< (tempInstallDirectory ? tempInstallDirectory : "(NULL)")
@@ -201,6 +204,29 @@ int cmCPackGenerator::InstallProject()
cmSystemTools::PutEnv("DESTDIR=");
}
+ // prepare default created directory permissions
+ mode_t default_dir_mode_v = 0;
+ mode_t* default_dir_mode = nullptr;
+ const char* default_dir_install_permissions =
+ this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_install_permissions && *default_dir_install_permissions) {
+ std::vector<std::string> items;
+ cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+ for (const auto& arg : items) {
+ if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '"
+ << arg
+ << "'."
+ " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS "
+ "value is invalid."
+ << std::endl);
+ return 0;
+ }
+ }
+
+ default_dir_mode = &default_dir_mode_v;
+ }
+
// If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them
// as listed
if (!this->InstallProjectViaInstallCommands(setDestDir,
@@ -218,15 +244,15 @@ int cmCPackGenerator::InstallProject()
// If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES
// then glob it and copy it to CPACK_TEMPORARY_DIRECTORY
// This is used in Source packaging
- if (!this->InstallProjectViaInstalledDirectories(setDestDir,
- tempInstallDirectory)) {
+ if (!this->InstallProjectViaInstalledDirectories(
+ setDestDir, tempInstallDirectory, default_dir_mode)) {
return 0;
}
// If the project is a CMAKE project then run pre-install
// and then read the cmake_install script to run it
- if (!this->InstallProjectViaInstallCMakeProjects(setDestDir,
- bareTempInstallDirectory)) {
+ if (!this->InstallProjectViaInstallCMakeProjects(
+ setDestDir, bareTempInstallDirectory, default_dir_mode)) {
return 0;
}
@@ -252,9 +278,9 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << ic << std::endl);
std::string output;
int retVal = 1;
- bool resB =
- cmSystemTools::RunSingleCommand(ic.c_str(), &output, &output, &retVal,
- nullptr, this->GeneratorVerbose, 0);
+ bool resB = cmSystemTools::RunSingleCommand(
+ ic.c_str(), &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/InstallOutput.log";
@@ -274,7 +300,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
}
int cmCPackGenerator::InstallProjectViaInstalledDirectories(
- bool setDestDir, const std::string& tempInstallDirectory)
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode)
{
(void)setDestDir;
(void)tempInstallDirectory;
@@ -287,7 +314,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
for (std::string const& ifr : ignoreFilesRegexString) {
cmCPackLogger(cmCPackLog::LOG_VERBOSE,
"Create ignore files regex for: " << ifr << std::endl);
- ignoreFilesRegex.push_back(ifr.c_str());
+ ignoreFilesRegex.emplace_back(ifr);
}
}
const char* installDirectories =
@@ -347,18 +374,17 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
continue;
}
std::string filePath = tempDir;
- filePath += "/" + subdir + "/" +
- cmSystemTools::RelativePath(top.c_str(), gf.c_str());
+ filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf);
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Copy file: "
<< inFile << " -> " << filePath << std::endl);
/* If the file is a symlink we will have to re-create it */
if (cmSystemTools::FileIsSymlink(inFile)) {
std::string targetFile;
std::string inFileRelative =
- cmSystemTools::RelativePath(top.c_str(), inFile.c_str());
+ cmSystemTools::RelativePath(top, inFile);
cmSystemTools::ReadSymlink(inFile, targetFile);
- symlinkedFiles.push_back(
- std::pair<std::string, std::string>(targetFile, inFileRelative));
+ symlinkedFiles.emplace_back(std::move(targetFile),
+ std::move(inFileRelative));
}
/* If it is not a symlink then do a plain copy */
else if (!(cmSystemTools::CopyFileIfDifferent(inFile.c_str(),
@@ -385,7 +411,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
// make sure directory exists for symlink
std::string destDir =
cmSystemTools::GetFilenamePath(symlinked.second);
- if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) {
+ if (!destDir.empty() &&
+ !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: "
<< destDir << "\nTrying to create symlink: "
<< symlinked.second << "--> " << symlinked.first
@@ -464,7 +491,8 @@ int cmCPackGenerator::InstallProjectViaInstallScript(
}
int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
- bool setDestDir, const std::string& baseTempInstallDirectory)
+ bool setDestDir, const std::string& baseTempInstallDirectory,
+ const mode_t* default_dir_mode)
{
const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS");
const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR");
@@ -573,7 +601,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
int retVal = 1;
bool resB = cmSystemTools::RunSingleCommand(
buildCommand.c_str(), &output, &output, &retVal,
- installDirectory.c_str(), this->GeneratorVerbose, 0);
+ installDirectory.c_str(), this->GeneratorVerbose,
+ cmDuration::zero());
if (!resB || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/PreinstallOutput.log";
@@ -609,6 +638,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
cm.GetCurrentSnapshot().SetDefaultDefinitions();
cm.AddCMakePaths();
cm.SetProgressCallback(cmCPackGeneratorProgress, this);
+ cm.SetTrace(this->Trace);
+ cm.SetTraceExpand(this->TraceExpand);
cmGlobalGenerator gg(&cm);
cmMakefile mf(&gg, cm.GetCurrentSnapshot());
if (!installSubDirectory.empty() && installSubDirectory != "/" &&
@@ -631,6 +662,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
}
}
+ const char* default_dir_inst_permissions =
+ this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_inst_permissions && *default_dir_inst_permissions) {
+ mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS",
+ default_dir_inst_permissions);
+ }
+
if (!setDestDir) {
tempInstallDirectory += this->GetPackagingInstallPrefix();
}
@@ -690,7 +728,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '"
<< dir << "'" << std::endl);
- if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) {
+ if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) {
cmCPackLogger(
cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: " << dir << std::endl);
@@ -700,8 +738,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
mf.AddDefinition("CMAKE_INSTALL_PREFIX",
tempInstallDirectory.c_str());
- if (!cmsys::SystemTools::MakeDirectory(
- tempInstallDirectory.c_str())) {
+ if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory,
+ default_dir_mode)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Problem creating temporary directory: "
<< tempInstallDirectory << std::endl);
@@ -733,9 +771,9 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
}
// Remember the list of files before installation
// of the current component (if we are in component install)
- const char* InstallPrefix = tempInstallDirectory.c_str();
+ std::string const& InstallPrefix = tempInstallDirectory;
std::vector<std::string> filesBefore;
- std::string findExpr(InstallPrefix);
+ std::string findExpr = tempInstallDirectory;
if (componentInstall) {
cmsys::Glob glB;
findExpr += "/*";
@@ -790,8 +828,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects(
std::string localFileName;
// Populate the File field of each component
for (fit = result.begin(); fit != diff; ++fit) {
- localFileName =
- cmSystemTools::RelativePath(InstallPrefix, fit->c_str());
+ localFileName = cmSystemTools::RelativePath(InstallPrefix, *fit);
localFileName =
localFileName.substr(localFileName.find_first_not_of('/'));
Components[installComponent].Files.push_back(localFileName);
@@ -954,10 +991,16 @@ int cmCPackGenerator::DoPackage()
*/
packageFileNames.push_back(tempPackageFileName ? tempPackageFileName : "");
toplevel = tempDirectory;
- if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
- cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
- << std::endl);
- return 0;
+ { // scope that enables package generators to run internal scripts with
+ // latest CMake policies enabled
+ cmMakefile::ScopePushPop pp{ this->MakefileMap };
+ this->MakefileMap->SetPolicyVersion(cmVersion::GetCMakeVersion());
+
+ if (!this->PackageFiles() || cmSystemTools::GetErrorOccuredFlag()) {
+ cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem compressing the directory"
+ << std::endl);
+ return 0;
+ }
}
/* Prepare checksum algorithm*/
diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h
index 4e3a6e038..c22f36b3f 100644
--- a/Source/CPack/cmCPackGenerator.h
+++ b/Source/CPack/cmCPackGenerator.h
@@ -12,6 +12,7 @@
#include "cmCPackComponentGroup.h"
#include "cmSystemTools.h"
+#include "cm_sys_stat.h"
class cmCPackLog;
class cmInstalledFile;
@@ -35,6 +36,16 @@ public:
}
/**
+ * Put underlying cmake scripts in trace mode.
+ */
+ void SetTrace(bool val) { this->Trace = val; }
+
+ /**
+ * Put underlying cmake scripts in expanded trace mode.
+ */
+ void SetTraceExpand(bool val) { this->TraceExpand = val; }
+
+ /**
* Returns true if the generator may work on this system.
* Rational:
* Some CPack generator may run on some host and may not on others
@@ -168,9 +179,11 @@ protected:
virtual int InstallProjectViaInstallScript(
bool setDestDir, const std::string& tempInstallDirectory);
virtual int InstallProjectViaInstalledDirectories(
- bool setDestDir, const std::string& tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode);
virtual int InstallProjectViaInstallCMakeProjects(
- bool setDestDir, const std::string& tempInstallDirectory);
+ bool setDestDir, const std::string& tempInstallDirectory,
+ const mode_t* default_dir_mode);
/**
* The various level of support of
@@ -292,6 +305,8 @@ protected:
ComponentPackageMethod componentPackageMethod;
cmCPackLog* Logger;
+ bool Trace;
+ bool TraceExpand;
private:
cmMakefile* MakefileMap;
diff --git a/Source/CPack/cmCPackGeneratorFactory.cxx b/Source/CPack/cmCPackGeneratorFactory.cxx
index 4b81bbc5f..47e752707 100644
--- a/Source/CPack/cmCPackGeneratorFactory.cxx
+++ b/Source/CPack/cmCPackGeneratorFactory.cxx
@@ -40,7 +40,7 @@
#include "cmCPackRPMGenerator.h"
#endif
-#ifdef _WIN32
+#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
#include "WiX/cmCPackWIXGenerator.h"
#endif
@@ -87,7 +87,7 @@ cmCPackGeneratorFactory::cmCPackGeneratorFactory()
this->RegisterGenerator("7Z", "7-Zip file format",
cmCPack7zGenerator::CreateGenerator);
}
-#ifdef _WIN32
+#if defined(_WIN32) || (defined(__CYGWIN__) && defined(HAVE_LIBUUID))
if (cmCPackWIXGenerator::CanGenerate()) {
this->RegisterGenerator("WIX", "MSI file format via WiX tools",
cmCPackWIXGenerator::CreateGenerator);
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index ddf104c93..3f7164a5d 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -5,6 +5,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
@@ -61,8 +62,7 @@ int cmCPackNSISGenerator::PackageFiles()
std::ostringstream str;
for (std::string const& file : files) {
std::string outputDir = "$INSTDIR";
- std::string fileN =
- cmSystemTools::RelativePath(toplevel.c_str(), file.c_str());
+ std::string fileN = cmSystemTools::RelativePath(toplevel, file);
if (!this->Components.empty()) {
const std::string::size_type pos = fileN.find('/');
@@ -89,8 +89,7 @@ int cmCPackNSISGenerator::PackageFiles()
std::ostringstream dstr;
for (std::string const& dir : dirs) {
std::string componentName;
- std::string fileN =
- cmSystemTools::RelativePath(toplevel.c_str(), dir.c_str());
+ std::string fileN = cmSystemTools::RelativePath(toplevel, dir);
if (fileN.empty()) {
continue;
}
@@ -115,7 +114,7 @@ int cmCPackNSISGenerator::PackageFiles()
dstr << " RMDir \"" << componentOutputDir << "\\" << fileN << "\""
<< std::endl;
if (!componentName.empty()) {
- this->Components[componentName].Directories.push_back(fileN);
+ this->Components[componentName].Directories.push_back(std::move(fileN));
}
}
cmCPackLogger(cmCPackLog::LOG_DEBUG, "Uninstall Dirs: " << dstr.str()
@@ -301,9 +300,9 @@ int cmCPackNSISGenerator::PackageFiles()
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
std::string output;
int retVal = 1;
- bool res =
- cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
- nullptr, this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ nsisCmd.c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
ofs << "# Run command: " << nsisCmd << std::endl
@@ -400,9 +399,9 @@ int cmCPackNSISGenerator::InitializeInternal()
<< std::endl);
std::string output;
int retVal = 1;
- bool resS =
- cmSystemTools::RunSingleCommand(nsisCmd.c_str(), &output, &output, &retVal,
- nullptr, this->GeneratorVerbose, 0);
+ bool resS = cmSystemTools::RunSingleCommand(
+ nsisCmd.c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
cmsys::RegularExpression versionRex("v([0-9]+.[0-9]+)");
cmsys::RegularExpression versionRexCVS("v(.*)\\.cvs");
if (!resS || retVal ||
@@ -668,8 +667,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
uploadDirectory += "/CPackUploads";
}
- if (!cmSystemTools::FileExists(uploadDirectory.c_str())) {
- if (!cmSystemTools::MakeDirectory(uploadDirectory.c_str())) {
+ if (!cmSystemTools::FileExists(uploadDirectory)) {
+ if (!cmSystemTools::MakeDirectory(uploadDirectory)) {
cmCPackLogger(cmCPackLog::LOG_ERROR,
"Unable to create NSIS upload directory "
<< uploadDirectory << std::endl);
@@ -682,7 +681,7 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
cmCPackLogger(cmCPackLog::LOG_OUTPUT,
"- Building downloaded component archive: " << archiveFile
<< std::endl);
- if (cmSystemTools::FileExists(archiveFile.c_str(), true)) {
+ if (cmSystemTools::FileExists(archiveFile, true)) {
if (!cmSystemTools::RemoveFile(archiveFile)) {
cmCPackLogger(cmCPackLog::LOG_ERROR, "Unable to remove archive file "
<< archiveFile << std::endl);
@@ -737,9 +736,9 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
zipListFileName.c_str());
std::string output;
int retVal = -1;
- int res = cmSystemTools::RunSingleCommand(cmd.c_str(), &output, &output,
- &retVal, dirName.c_str(),
- cmSystemTools::OUTPUT_NONE, 0);
+ int res = cmSystemTools::RunSingleCommand(
+ cmd.c_str(), &output, &output, &retVal, dirName.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero());
if (!res || retVal) {
std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
tmpFile += "/CompressZip.log";
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 8d3c40c5c..e750de3ea 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -6,6 +6,7 @@
#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cm_sys_stat.h"
@@ -154,9 +155,9 @@ int cmCPackOSXX11Generator::PackageFiles()
int numTries = 10;
bool res = false;
while (numTries > 0) {
- res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
- &output, &retVal, nullptr,
- this->GeneratorVerbose, 0);
+ res = cmSystemTools::RunSingleCommand(
+ dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (res && !retVal) {
numTries = -1;
break;
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index dbcb02231..c515b857f 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -13,6 +13,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
#include "cmXMLWriter.h"
@@ -295,9 +296,9 @@ int cmCPackPackageMakerGenerator::PackageFiles()
int numTries = 10;
bool res = false;
while (numTries > 0) {
- res = cmSystemTools::RunSingleCommand(dmgCmd.str().c_str(), &output,
- &output, &retVal, nullptr,
- this->GeneratorVerbose, 0);
+ res = cmSystemTools::RunSingleCommand(
+ dmgCmd.str().c_str(), &output, &output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
if (res && !retVal) {
numTries = -1;
break;
@@ -467,7 +468,8 @@ bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
std::string output;
int retVal = 1;
bool res = cmSystemTools::RunSingleCommand(
- command, &output, &output, &retVal, nullptr, this->GeneratorVerbose, 0);
+ command, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
+ cmDuration::zero());
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running package maker"
<< std::endl);
if (!res || retVal) {
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index 6a6dc828f..57cf7ea11 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -8,6 +8,7 @@
#include "cmCPackComponentGroup.h"
#include "cmCPackLog.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"
@@ -145,9 +146,9 @@ bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
std::string output, error_output;
int retVal = 1;
- bool res = cmSystemTools::RunSingleCommand(command.c_str(), &output,
- &error_output, &retVal, nullptr,
- this->GeneratorVerbose, 0);
+ bool res = cmSystemTools::RunSingleCommand(
+ command.c_str(), &output, &error_output, &retVal, nullptr,
+ this->GeneratorVerbose, cmDuration::zero());
cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Done running command" << std::endl);
if (!res || retVal) {
cmGeneratedFileStream ofs(tmpFile.c_str());
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index addb54ea0..507a10c3e 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -43,6 +43,8 @@ static const char* cmDocumentationOptions[][2] = {
{ "-D <var>=<value>", "Set a CPack variable." },
{ "--config <config file>", "Specify the config file." },
{ "--verbose,-V", "enable verbose output" },
+ { "--trace", "Put underlying cmake scripts in trace mode." },
+ { "--trace-expand", "Put underlying cmake scripts in expanded trace mode." },
{ "--debug", "enable debug output (for CPack developers)" },
{ "-P <package name>", "override/define CPACK_PACKAGE_NAME" },
{ "-R <package version>", "override/define CPACK_PACKAGE_VERSION" },
@@ -98,6 +100,8 @@ int main(int argc, char const* const* argv)
argc = args.argc();
argv = args.argv();
+ cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
cmCPackLog log;
@@ -106,8 +110,6 @@ int main(int argc, char const* const* argv)
log.SetOutputPrefix("CPack: ");
log.SetVerbosePrefix("CPack Verbose: ");
- cmSystemTools::EnableMSVCDebugHook();
-
if (cmSystemTools::GetCurrentWorkingDirectory().empty()) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Current working directory cannot be established."
@@ -119,6 +121,8 @@ int main(int argc, char const* const* argv)
bool help = false;
bool helpVersion = false;
bool verbose = false;
+ bool trace = false;
+ bool traceExpand = false;
bool debug = false;
std::string helpFull;
std::string helpMAN;
@@ -154,6 +158,10 @@ int main(int argc, char const* const* argv)
arg.AddArgument("--debug", argT::NO_ARGUMENT, &debug, "-V");
arg.AddArgument("--config", argT::SPACE_ARGUMENT, &cpackConfigFile,
"CPack configuration file");
+ arg.AddArgument("--trace", argT::NO_ARGUMENT, &trace,
+ "Put underlying cmake scripts in trace mode.");
+ arg.AddArgument("--trace-expand", argT::NO_ARGUMENT, &traceExpand,
+ "Put underlying cmake scripts in expanded trace mode.");
arg.AddArgument("-C", argT::SPACE_ARGUMENT, &cpackBuildConfig,
"CPack build configuration");
arg.AddArgument("-G", argT::SPACE_ARGUMENT, &generator, "CPack generator");
@@ -197,6 +205,14 @@ int main(int argc, char const* const* argv)
globalMF.AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0");
#endif
+ if (trace) {
+ cminst.SetTrace(true);
+ }
+ if (traceExpand) {
+ cminst.SetTrace(true);
+ cminst.SetTraceExpand(true);
+ }
+
bool cpackConfigFileSpecified = true;
if (cpackConfigFile.empty()) {
cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory();
@@ -244,7 +260,7 @@ int main(int argc, char const* const* argv)
globalMF.AddDefinition("CPACK_BUILD_CONFIG", cpackBuildConfig.c_str());
}
- if (cmSystemTools::FileExists(cpackConfigFile.c_str())) {
+ if (cmSystemTools::FileExists(cpackConfigFile)) {
cpackConfigFile = cmSystemTools::CollapseFullPath(cpackConfigFile);
cmCPack_Log(&log, cmCPackLog::LOG_VERBOSE,
"Read CPack configuration file: " << cpackConfigFile
@@ -340,6 +356,10 @@ int main(int argc, char const* const* argv)
<< std::endl);
parsed = 0;
}
+
+ cpackGenerator->SetTrace(trace);
+ cpackGenerator->SetTraceExpand(traceExpand);
+
if (parsed && !cpackGenerator->Initialize(gen, mf)) {
cmCPack_Log(&log, cmCPackLog::LOG_ERROR,
"Cannot initialize the generator " << gen
@@ -412,7 +432,7 @@ int main(int argc, char const* const* argv)
cmDocumentationEntry e;
e.Name = g.first;
e.Brief = g.second;
- v.push_back(e);
+ v.push_back(std::move(e));
}
doc.SetSection("Generators", v);
diff --git a/Source/CTest/cmCTestBatchTestHandler.cxx b/Source/CTest/cmCTestBatchTestHandler.cxx
deleted file mode 100644
index 2eed8bed9..000000000
--- a/Source/CTest/cmCTestBatchTestHandler.cxx
+++ /dev/null
@@ -1,123 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmCTestBatchTestHandler.h"
-
-#include "cmCTest.h"
-#include "cmCTestMultiProcessHandler.h"
-#include "cmCTestTestHandler.h"
-#include "cmProcess.h"
-#include "cmSystemTools.h"
-
-#include <map>
-#include <utility>
-#include <vector>
-
-cmCTestBatchTestHandler::~cmCTestBatchTestHandler()
-{
-}
-
-void cmCTestBatchTestHandler::RunTests()
-{
- this->WriteBatchScript();
- this->SubmitBatchScript();
-}
-
-void cmCTestBatchTestHandler::WriteBatchScript()
-{
- this->Script = this->CTest->GetBinaryDir() + "/Testing/CTestBatch.txt";
- cmsys::ofstream fout;
- fout.open(this->Script.c_str());
- fout << "#!/bin/sh\n";
-
- for (auto const& t : this->Tests) {
- this->WriteSrunArgs(t.first, fout);
- this->WriteTestCommand(t.first, fout);
- fout << "\n";
- }
- fout.flush();
- fout.close();
-}
-
-void cmCTestBatchTestHandler::WriteSrunArgs(int test, std::ostream& fout)
-{
- cmCTestTestHandler::cmCTestTestProperties* properties =
- this->Properties[test];
-
- fout << "srun ";
- // fout << "--jobid=" << test << " ";
- fout << "-J=" << properties->Name << " ";
-
- // Write dependency information
- /*if(!this->Tests[test].empty())
- {
- fout << "-P=afterany";
- for(TestSet::iterator i = this->Tests[test].begin();
- i != this->Tests[test].end(); ++i)
- {
- fout << ":" << *i;
- }
- fout << " ";
- }*/
- if (properties->RunSerial) {
- fout << "--exclusive ";
- }
- if (properties->Processors > 1) {
- fout << "-n" << properties->Processors << " ";
- }
-}
-
-void cmCTestBatchTestHandler::WriteTestCommand(int test, std::ostream& fout)
-{
- std::vector<std::string> args = this->Properties[test]->Args;
- std::vector<std::string> processArgs;
- std::string command;
-
- command = this->TestHandler->FindTheExecutable(args[1].c_str());
- command = cmSystemTools::ConvertToOutputPath(command.c_str());
-
- // Prepends memcheck args to our command string if this is a memcheck
- this->TestHandler->GenerateTestCommand(processArgs, test);
- processArgs.push_back(command);
-
- for (std::string const& arg : processArgs) {
- fout << arg << " ";
- }
-
- std::vector<std::string>::iterator i = args.begin();
- ++i; // the test name
- ++i; // the executable (command)
- if (args.size() > 2) {
- fout << "'";
- }
- while (i != args.end()) {
- fout << "\"" << *i << "\""; // args to the test executable
- ++i;
-
- if (i == args.end() && args.size() > 2) {
- fout << "'";
- }
- fout << " ";
- }
- // TODO ZACH build TestResult.FullCommandLine
- // this->TestResult.FullCommandLine = this->TestCommand;
-}
-
-void cmCTestBatchTestHandler::SubmitBatchScript()
-{
- cmProcess sbatch;
- std::vector<std::string> args;
- args.push_back(this->Script);
- args.push_back("-o");
- args.push_back(this->CTest->GetBinaryDir() + "/Testing/CTestBatch.txt");
-
- sbatch.SetCommand("sbatch");
- sbatch.SetCommandArguments(args);
- /*if(sbatch.StartProcess())
- {
- //success condition
- }
- else
- {
- //fail condition
- }*/
-}
diff --git a/Source/CTest/cmCTestBatchTestHandler.h b/Source/CTest/cmCTestBatchTestHandler.h
deleted file mode 100644
index 42f87bddd..000000000
--- a/Source/CTest/cmCTestBatchTestHandler.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmCTestBatchTestHandler_h
-#define cmCTestBatchTestHandler_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include "cmCTestMultiProcessHandler.h"
-#include "cmsys/FStream.hxx"
-#include <string>
-
-/** \class cmCTestBatchTestHandler
- * \brief run parallel ctest
- *
- * cmCTestBatchTestHandler
- */
-class cmCTestBatchTestHandler : public cmCTestMultiProcessHandler
-{
-public:
- ~cmCTestBatchTestHandler() override;
- void RunTests() override;
-
-protected:
- void WriteBatchScript();
- void WriteSrunArgs(int test, std::ostream& fout);
- void WriteTestCommand(int test, std::ostream& fout);
-
- void SubmitBatchScript();
-
- std::string Script;
-};
-
-#endif
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index a0d68a066..2e1ea4c3a 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -10,6 +10,8 @@
#include "cmake.h"
#include "cmsys/Process.h"
+#include <chrono>
+#include <ratio>
#include <stdlib.h>
cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
@@ -17,7 +19,7 @@ cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler()
this->BuildTwoConfig = false;
this->BuildNoClean = false;
this->BuildNoCMake = false;
- this->Timeout = 0;
+ this->Timeout = cmDuration::zero();
}
void cmCTestBuildAndTestHandler::Initialize()
@@ -49,19 +51,13 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
args.push_back(cmSystemTools::GetCMakeCommand());
args.push_back(this->SourceDir);
if (!this->BuildGenerator.empty()) {
- std::string generator = "-G";
- generator += this->BuildGenerator;
- args.push_back(generator);
+ args.push_back("-G" + this->BuildGenerator);
}
if (!this->BuildGeneratorPlatform.empty()) {
- std::string platform = "-A";
- platform += this->BuildGeneratorPlatform;
- args.push_back(platform);
+ args.push_back("-A" + this->BuildGeneratorPlatform);
}
if (!this->BuildGeneratorToolset.empty()) {
- std::string toolset = "-T";
- toolset += this->BuildGeneratorToolset;
- args.push_back(toolset);
+ args.push_back("-T" + this->BuildGeneratorToolset);
}
const char* config = nullptr;
@@ -75,8 +71,7 @@ int cmCTestBuildAndTestHandler::RunCMake(std::string* outstring,
#endif
if (config) {
- std::string btype = "-DCMAKE_BUILD_TYPE:STRING=" + std::string(config);
- args.push_back(btype);
+ args.push_back("-DCMAKE_BUILD_TYPE:STRING=" + std::string(config));
}
for (std::string const& opt : this->BuildOptions) {
@@ -192,13 +187,13 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
// we need to honor the timeout specified, the timeout include cmake, build
// and test time
- double clock_start = cmSystemTools::GetTime();
+ auto clock_start = std::chrono::steady_clock::now();
// make sure the binary dir is there
out << "Internal cmake changing into directory: " << this->BinaryDir
<< std::endl;
if (!cmSystemTools::FileIsDirectory(this->BinaryDir)) {
- cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
+ cmSystemTools::MakeDirectory(this->BinaryDir);
}
cmWorkingDirectory workdir(this->BinaryDir);
@@ -222,10 +217,11 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
this->BuildTargets.push_back("");
}
for (std::string const& tar : this->BuildTargets) {
- double remainingTime = 0;
- if (this->Timeout > 0) {
- remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
- if (remainingTime <= 0) {
+ cmDuration remainingTime = std::chrono::seconds(0);
+ if (this->Timeout > cmDuration::zero()) {
+ remainingTime =
+ this->Timeout - (std::chrono::steady_clock::now() - clock_start);
+ if (remainingTime <= std::chrono::seconds(0)) {
if (outstring) {
*outstring = "--build-and-test timeout exceeded. ";
}
@@ -284,7 +280,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
cmCTestTestHandler::FindExecutable(this->CTest, this->TestCommand.c_str(),
resultingConfig, extraPaths, failed);
- if (!cmSystemTools::FileExists(fullPath.c_str())) {
+ if (!cmSystemTools::FileExists(fullPath)) {
out << "Could not find path to executable, perhaps it was not built: "
<< this->TestCommand << "\n";
out << "tried to find it in these places:\n";
@@ -320,10 +316,11 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
out << "\n";
// how much time is remaining
- double remainingTime = 0;
- if (this->Timeout > 0) {
- remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start;
- if (remainingTime <= 0) {
+ cmDuration remainingTime = std::chrono::seconds(0);
+ if (this->Timeout > cmDuration::zero()) {
+ remainingTime =
+ this->Timeout - (std::chrono::steady_clock::now() - clock_start);
+ if (remainingTime <= std::chrono::seconds(0)) {
if (outstring) {
*outstring = "--build-and-test timeout exceeded. ";
}
@@ -361,7 +358,7 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
idx++;
this->BinaryDir = allArgs[idx];
// dir must exist before CollapseFullPath is called
- cmSystemTools::MakeDirectory(this->BinaryDir.c_str());
+ cmSystemTools::MakeDirectory(this->BinaryDir);
this->BinaryDir = cmSystemTools::CollapseFullPath(this->BinaryDir);
this->SourceDir = cmSystemTools::CollapseFullPath(this->SourceDir);
} else {
@@ -391,7 +388,7 @@ int cmCTestBuildAndTestHandler::ProcessCommandLineArguments(
}
if (currentArg.find("--test-timeout", 0) == 0 && idx < allArgs.size() - 1) {
idx++;
- this->Timeout = atof(allArgs[idx].c_str());
+ this->Timeout = cmDuration(atof(allArgs[idx].c_str()));
}
if (currentArg == "--build-generator" && idx < allArgs.size() - 1) {
idx++;
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.h b/Source/CTest/cmCTestBuildAndTestHandler.h
index f19cb67ce..5e6d0aad2 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.h
+++ b/Source/CTest/cmCTestBuildAndTestHandler.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
#include <sstream>
#include <stddef.h>
@@ -67,7 +68,7 @@ protected:
std::vector<std::string> TestCommandArgs;
std::vector<std::string> BuildTargets;
bool BuildNoCMake;
- double Timeout;
+ cmDuration Timeout;
};
#endif
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index f4fc76929..ce6fbc75d 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -4,6 +4,7 @@
#include "cmAlgorithms.h"
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmFileTimeComparison.h"
#include "cmGeneratedFileStream.h"
#include "cmMakefile.h"
@@ -17,6 +18,7 @@
#include <set>
#include <stdlib.h>
#include <string.h>
+#include <utility>
static const char* cmCTestErrorMatches[] = {
"^[Bb]us [Ee]rror",
@@ -282,7 +284,7 @@ int cmCTestBuildHandler::ProcessHandler()
this->Quiet);
// do we have time for this
- if (this->CTest->GetRemainingTimeAllowed() < 120) {
+ if (this->CTest->GetRemainingTimeAllowed() < std::chrono::minutes(2)) {
return 0;
}
@@ -294,7 +296,7 @@ int cmCTestBuildHandler::ProcessHandler()
cmCTestWarningErrorFileLine[entry].RegularExpressionString)) {
r.FileIndex = cmCTestWarningErrorFileLine[entry].FileIndex;
r.LineIndex = cmCTestWarningErrorFileLine[entry].LineIndex;
- this->ErrorWarningFileLineRegex.push_back(r);
+ this->ErrorWarningFileLineRegex.push_back(std::move(r));
} else {
cmCTestLog(
this->CTest, ERROR_MESSAGE, "Problem Compiling regular expression: "
@@ -327,7 +329,7 @@ int cmCTestBuildHandler::ProcessHandler()
// Create a last build log
cmGeneratedFileStream ofs;
- double elapsed_time_start = cmSystemTools::GetTime();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
if (!this->StartLogFile("Build", ofs)) {
cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file"
<< std::endl);
@@ -406,7 +408,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()) {
@@ -420,8 +422,9 @@ int cmCTestBuildHandler::ProcessHandler()
// Remember end build time and calculate elapsed time
this->EndBuild = this->CTest->CurrentTime();
- this->EndBuildTime = cmSystemTools::GetTime();
- double elapsed_build_time = cmSystemTools::GetTime() - elapsed_time_start;
+ this->EndBuildTime = std::chrono::system_clock::now();
+ auto elapsed_build_time =
+ std::chrono::steady_clock::now() - elapsed_time_start;
// Cleanups strings in the errors and warnings list.
if (!this->SimplifySourceDir.empty()) {
@@ -486,8 +489,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());
}
@@ -634,7 +636,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
}
void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
- double elapsed_build_time)
+ cmDuration elapsed_build_time)
{
xml.StartElement("Log");
xml.Attribute("Encoding", "base64");
@@ -642,9 +644,11 @@ void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml,
xml.EndElement(); // Log
xml.Element("EndDateTime", this->EndBuild);
- xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime));
- xml.Element("ElapsedMinutes",
- static_cast<int>(elapsed_build_time / 6) / 10.0);
+ xml.Element("EndBuildTime", this->EndBuildTime);
+ xml.Element(
+ "ElapsedMinutes",
+ std::chrono::duration_cast<std::chrono::minutes>(elapsed_build_time)
+ .count());
xml.EndElement(); // Build
this->CTest->EndXML(xml);
}
@@ -705,7 +709,7 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
if (this->Handler->UseCTestLaunch) {
// Enable launcher fragments.
- cmSystemTools::MakeDirectory(launchDir.c_str());
+ cmSystemTools::MakeDirectory(launchDir);
this->WriteLauncherConfig();
std::string launchEnv = "CTEST_LAUNCH_LOGS=";
launchEnv += launchDir;
@@ -892,7 +896,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
errorwarning.PreContext.clear();
errorwarning.PostContext.clear();
errorwarning.Error = false;
- this->ErrorsAndWarnings.push_back(errorwarning);
+ this->ErrorsAndWarnings.push_back(std::move(errorwarning));
this->TotalWarnings++;
}
}
@@ -915,7 +919,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal,
errorwarning.PreContext.clear();
errorwarning.PostContext.clear();
errorwarning.Error = true;
- this->ErrorsAndWarnings.push_back(errorwarning);
+ this->ErrorsAndWarnings.push_back(std::move(errorwarning));
this->TotalErrors++;
cmCTestLog(this->CTest, ERROR_MESSAGE, "There was an error: "
<< cmsysProcess_GetErrorString(cp) << std::endl);
@@ -1007,7 +1011,7 @@ void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length,
this->PreContext.clear();
// Store report
- this->ErrorsAndWarnings.push_back(errorwarning);
+ this->ErrorsAndWarnings.push_back(std::move(errorwarning));
this->LastErrorOrWarning = this->ErrorsAndWarnings.end() - 1;
this->PostContextCount = 0;
} else {
diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h
index 6e71ad6ae..a9b121b24 100644
--- a/Source/CTest/cmCTestBuildHandler.h
+++ b/Source/CTest/cmCTestBuildHandler.h
@@ -7,8 +7,10 @@
#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
#include "cmProcessOutput.h"
#include "cmsys/RegularExpression.hxx"
+#include <chrono>
#include <deque>
#include <iosfwd>
#include <stddef.h>
@@ -86,14 +88,14 @@ private:
void GenerateXMLHeader(cmXMLWriter& xml);
void GenerateXMLLaunched(cmXMLWriter& xml);
void GenerateXMLLogScraped(cmXMLWriter& xml);
- void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time);
+ void GenerateXMLFooter(cmXMLWriter& xml, cmDuration elapsed_build_time);
bool IsLaunchedErrorFile(const char* fname);
bool IsLaunchedWarningFile(const char* fname);
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/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index c44b86605..7b5c3bcb5 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -57,7 +57,7 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
}
const std::string cmakelists_file = source_dir + "/CMakeLists.txt";
- if (!cmSystemTools::FileExists(cmakelists_file.c_str())) {
+ if (!cmSystemTools::FileExists(cmakelists_file)) {
std::ostringstream e;
e << "CMakeLists.txt file does not exist [" << cmakelists_file << "]";
this->SetError(e.str());
diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx
index 56a038e38..821a94a00 100644
--- a/Source/CTest/cmCTestConfigureHandler.cxx
+++ b/Source/CTest/cmCTestConfigureHandler.cxx
@@ -3,10 +3,11 @@
#include "cmCTestConfigureHandler.h"
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
-#include "cmSystemTools.h"
#include "cmXMLWriter.h"
+#include <chrono>
#include <ostream>
#include <string>
@@ -43,7 +44,7 @@ int cmCTestConfigureHandler::ProcessHandler()
return -1;
}
- double elapsed_time_start = cmSystemTools::GetTime();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
std::string output;
int retVal = 0;
int res = 0;
@@ -55,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);
@@ -64,7 +64,8 @@ int cmCTestConfigureHandler::ProcessHandler()
"Configure with command: " << cCommand << std::endl,
this->Quiet);
res = this->CTest->RunMakeCommand(cCommand.c_str(), output, &retVal,
- buildDirectory.c_str(), 0, ofs);
+ buildDirectory.c_str(),
+ cmDuration::zero(), ofs);
if (ofs) {
ofs.close();
@@ -82,12 +83,11 @@ 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(
- "ElapsedMinutes",
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
- 10.0);
+ 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)
+ .count());
xml.EndElement(); // Configure
this->CTest->EndXML(xml);
}
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 56eeceb0b..9c66e73f3 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -3,6 +3,7 @@
#include "cmCTestCoverageHandler.h"
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmParseBlanketJSCoverage.h"
#include "cmParseCacheCoverage.h"
@@ -21,6 +22,7 @@
#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <chrono>
#include <iomanip>
#include <iterator>
#include <sstream>
@@ -39,7 +41,7 @@ public:
{
this->Process = cmsysProcess_New();
this->PipeState = -1;
- this->TimeOut = -1;
+ this->TimeOut = cmDuration(-1);
}
~cmCTestRunProcess()
{
@@ -63,7 +65,7 @@ public:
}
}
void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
- void SetTimeout(double t) { this->TimeOut = t; }
+ void SetTimeout(cmDuration t) { this->TimeOut = t; }
bool StartProcess()
{
std::vector<const char*> args;
@@ -78,8 +80,8 @@ public:
}
cmsysProcess_SetOption(this->Process, cmsysProcess_Option_HideWindow, 1);
- if (this->TimeOut != -1) {
- cmsysProcess_SetTimeout(this->Process, this->TimeOut);
+ if (this->TimeOut >= cmDuration::zero()) {
+ cmsysProcess_SetTimeout(this->Process, this->TimeOut.count());
}
cmsysProcess_Execute(this->Process);
this->PipeState = cmsysProcess_GetState(this->Process);
@@ -107,7 +109,7 @@ private:
cmsysProcess* Process;
std::vector<std::string> CommandLineStrings;
std::string WorkingDirectory;
- double TimeOut;
+ cmDuration TimeOut;
};
cmCTestCoverageHandler::cmCTestCoverageHandler()
@@ -173,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);
}
@@ -239,7 +240,7 @@ bool cmCTestCoverageHandler::ShouldIDoCoverage(std::string const& file,
// If it is the same as fileDir, then ignore, otherwise check.
std::string relPath;
if (!checkDir.empty()) {
- relPath = cmSystemTools::RelativePath(checkDir.c_str(), fFile.c_str());
+ relPath = cmSystemTools::RelativePath(checkDir, fFile);
} else {
relPath = fFile;
}
@@ -276,13 +277,12 @@ int cmCTestCoverageHandler::ProcessHandler()
this->CTest->ClearSubmitFiles(cmCTest::PartCoverage);
int error = 0;
// do we have time for this
- if (this->CTest->GetRemainingTimeAllowed() < 120) {
+ if (this->CTest->GetRemainingTimeAllowed() < std::chrono::minutes(2)) {
return error;
}
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");
@@ -290,13 +290,14 @@ int cmCTestCoverageHandler::ProcessHandler()
this->LoadLabels();
cmGeneratedFileStream ofs;
- double elapsed_time_start = cmSystemTools::GetTime();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
if (!this->StartLogFile("Coverage", ofs)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create LastCoverage.log file" << std::endl);
}
- ofs << "Performing coverage: " << elapsed_time_start << std::endl;
+ ofs << "Performing coverage: "
+ << elapsed_time_start.time_since_epoch().count() << std::endl;
this->CleanCoverageLogFiles(ofs);
cmSystemTools::ConvertToUnixSlashes(sourceDir);
@@ -449,7 +450,7 @@ int cmCTestCoverageHandler::ProcessHandler()
"Process file: " << fullFileName << std::endl,
this->Quiet);
- if (!cmSystemTools::FileExists(fullFileName.c_str())) {
+ if (!cmSystemTools::FileExists(fullFileName)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot find file: " << fullFileName << std::endl);
continue;
@@ -619,12 +620,11 @@ 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(
- "ElapsedMinutes",
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
- 10.0);
+ 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)
+ .count());
covSumXML.EndElement(); // Coverage
this->CTest->EndXML(covSumXML);
@@ -718,7 +718,7 @@ int cmCTestCoverageHandler::HandleCoberturaCoverage(
// build the find file string with the directory from above
coverageXMLFile += "/coverage.xml";
- if (cmSystemTools::FileExists(coverageXMLFile.c_str())) {
+ if (cmSystemTools::FileExists(coverageXMLFile)) {
// If file exists, parse it
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Parsing Cobertura XML file: " << coverageXMLFile
@@ -741,7 +741,7 @@ int cmCTestCoverageHandler::HandleMumpsCoverage(
cmParseGTMCoverage cov(*cont, this->CTest);
std::string coverageFile =
this->CTest->GetBinaryDir() + "/gtm_coverage.mcov";
- if (cmSystemTools::FileExists(coverageFile.c_str())) {
+ if (cmSystemTools::FileExists(coverageFile)) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Parsing Cache Coverage: " << coverageFile << std::endl,
this->Quiet);
@@ -754,7 +754,7 @@ int cmCTestCoverageHandler::HandleMumpsCoverage(
this->Quiet);
cmParseCacheCoverage ccov(*cont, this->CTest);
coverageFile = this->CTest->GetBinaryDir() + "/cache_coverage.cmcov";
- if (cmSystemTools::FileExists(coverageFile.c_str())) {
+ if (cmSystemTools::FileExists(coverageFile)) {
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"Parsing Cache Coverage: " << coverageFile << std::endl,
this->Quiet);
@@ -975,7 +975,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir.c_str());
+ cmSystemTools::MakeDirectory(tempDir);
cmWorkingDirectory workdir(tempDir);
int gcovStyle = 0;
@@ -1024,7 +1024,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
*cont->OFS << "* Run coverage for: " << fileDir << std::endl;
*cont->OFS << " Command: " << command << std::endl;
int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
- tempDir.c_str(), 0 /*this->TimeOut*/);
+ tempDir.c_str(),
+ cmDuration::zero() /*this->TimeOut*/);
*cont->OFS << " Output: " << output << std::endl;
*cont->OFS << " Errors: " << errors << std::endl;
@@ -1388,7 +1389,8 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
*cont->OFS << "* Run coverage for: " << fileDir << std::endl;
*cont->OFS << " Command: " << command << std::endl;
int res = this->CTest->RunCommand(covargs, &output, &errors, &retVal,
- fileDir.c_str(), 0 /*this->TimeOut*/);
+ fileDir.c_str(),
+ cmDuration::zero() /*this->TimeOut*/);
*cont->OFS << " Output: " << output << std::endl;
*cont->OFS << " Errors: " << errors << std::endl;
@@ -1644,7 +1646,7 @@ int cmCTestCoverageHandler::HandleTracePyCoverage(
std::string testingDir = this->CTest->GetBinaryDir() + "/Testing";
std::string tempDir = testingDir + "/CoverageInfo";
- cmSystemTools::MakeDirectory(tempDir.c_str());
+ cmSystemTools::MakeDirectory(tempDir);
int file_count = 0;
for (std::string const& file : files) {
@@ -1740,11 +1742,11 @@ std::string cmCTestCoverageHandler::FindFile(
cmSystemTools::GetFilenameWithoutLastExtension(fileName);
// First check in source and binary directory
std::string fullName = cont->SourceDir + "/" + fileNameNoE + ".py";
- if (cmSystemTools::FileExists(fullName.c_str())) {
+ if (cmSystemTools::FileExists(fullName)) {
return fullName;
}
fullName = cont->BinaryDir + "/" + fileNameNoE + ".py";
- if (cmSystemTools::FileExists(fullName.c_str())) {
+ if (cmSystemTools::FileExists(fullName)) {
return fullName;
}
return "";
@@ -1963,12 +1965,11 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
return 0;
}
this->CTest->StartXML(xml, this->AppendXML);
- double elapsed_time_start = cmSystemTools::GetTime();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
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:
@@ -2011,7 +2012,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
}
std::string file = sourceFile;
coveredFileNames.insert(file);
- if (!cmSystemTools::FileIsFullPath(sourceFile.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(sourceFile)) {
// file will be relative to the binary dir
file = cont->BinaryDir;
file += "/";
@@ -2089,11 +2090,11 @@ 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(
- "ElapsedMinutes",
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
- 10.0);
+ 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)
+ .count());
xml.EndElement(); // Coverage
this->CTest->EndXML(xml);
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index 8cb795e22..e85af5edb 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -113,7 +113,7 @@ std::string cmCTestGIT::FindGitDir()
// are a Windows application. Run "cygpath" to get Windows path.
std::string cygpath_exe = cmSystemTools::GetFilenamePath(git);
cygpath_exe += "/cygpath.exe";
- if (cmSystemTools::FileExists(cygpath_exe.c_str())) {
+ if (cmSystemTools::FileExists(cygpath_exe)) {
char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(),
0 };
OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line);
@@ -249,7 +249,7 @@ bool cmCTestGIT::UpdateImpl()
if (this->GetGitVersion() < cmCTestGITVersion(1, 6, 5, 0)) {
recursive = nullptr;
// No need to require >= 1.6.5 if there are no submodules.
- if (cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str())) {
+ if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) {
this->Log << "Git < 1.6.5 cannot update submodules recursively\n";
}
}
@@ -258,7 +258,7 @@ bool cmCTestGIT::UpdateImpl()
if (this->GetGitVersion() < cmCTestGITVersion(1, 8, 1, 0)) {
sync_recursive = nullptr;
// No need to require >= 1.8.1 if there are no submodules.
- if (cmSystemTools::FileExists((top_dir + "/.gitmodules").c_str())) {
+ if (cmSystemTools::FileExists(top_dir + "/.gitmodules")) {
this->Log << "Git < 1.8.1 cannot synchronize submodules recursively\n";
}
}
@@ -553,15 +553,15 @@ private:
void DoHeaderLine()
{
// Look for header fields that we need.
- if (cmHasLiteralPrefix(this->Line.c_str(), "commit ")) {
+ if (cmHasLiteralPrefix(this->Line, "commit ")) {
this->Rev.Rev = this->Line.c_str() + 7;
- } else if (cmHasLiteralPrefix(this->Line.c_str(), "author ")) {
+ } else if (cmHasLiteralPrefix(this->Line, "author ")) {
Person author;
this->ParsePerson(this->Line.c_str() + 7, author);
this->Rev.Author = author.Name;
this->Rev.EMail = author.EMail;
this->Rev.Date = this->FormatDateTime(author);
- } else if (cmHasLiteralPrefix(this->Line.c_str(), "committer ")) {
+ } else if (cmHasLiteralPrefix(this->Line, "committer ")) {
Person committer;
this->ParsePerson(this->Line.c_str() + 10, committer);
this->Rev.Committer = committer.Name;
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index a1249f5b3..30f76a927 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -377,11 +377,10 @@ void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml)
cmSystemTools::ConvertToUnixSlashes(source);
// If file is in source tree use its relative location.
- if (cmSystemTools::FileIsFullPath(this->SourceDir.c_str()) &&
- cmSystemTools::FileIsFullPath(source.c_str()) &&
+ if (cmSystemTools::FileIsFullPath(this->SourceDir) &&
+ cmSystemTools::FileIsFullPath(source) &&
cmSystemTools::IsSubDirectory(source, this->SourceDir)) {
- source =
- cmSystemTools::RelativePath(this->SourceDir.c_str(), source.c_str());
+ source = cmSystemTools::RelativePath(this->SourceDir, source);
}
xml.Element("SourceFile", source);
@@ -564,7 +563,7 @@ void cmCTestLaunch::LoadScrapeRules(
std::string line;
cmsys::RegularExpression rex;
while (cmSystemTools::GetLineFromStream(fin, line)) {
- if (rex.compile(line.c_str())) {
+ if (rex.compile(line)) {
regexps.push_back(rex);
}
}
@@ -629,8 +628,7 @@ void cmCTestLaunch::LoadConfig()
cmMakefile mf(&gg, cm.GetCurrentSnapshot());
std::string fname = this->LogDir;
fname += "CTestLaunchConfig.cmake";
- if (cmSystemTools::FileExists(fname.c_str()) &&
- mf.ReadListFile(fname.c_str())) {
+ if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname.c_str())) {
this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
cmSystemTools::ConvertToUnixSlashes(this->SourceDir);
}
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 3efb039ea..cb1d947c8 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -3,6 +3,7 @@
#include "cmCTestMemCheckHandler.h"
#include "cmCTest.h"
+#include "cmDuration.h"
#include "cmSystemTools.h"
#include "cmXMLParser.h"
#include "cmXMLWriter.h"
@@ -10,9 +11,11 @@
#include "cmsys/FStream.hxx"
#include "cmsys/Glob.hxx"
#include "cmsys/RegularExpression.hxx"
+#include <chrono>
#include <iostream>
#include <sstream>
#include <string.h>
+#include <utility>
struct CatToErrorType
{
@@ -160,7 +163,7 @@ void cmCTestMemCheckHandler::GenerateTestCommand(
std::string index;
std::ostringstream stream;
std::string memcheckcommand =
- cmSystemTools::ConvertToOutputPath(this->MemoryTester.c_str());
+ cmSystemTools::ConvertToOutputPath(this->MemoryTester);
stream << test;
index = stream.str();
for (std::string arg : this->MemoryTesterDynamicOptions) {
@@ -175,7 +178,7 @@ void cmCTestMemCheckHandler::GenerateTestCommand(
}
// Create a copy of the memory tester environment variable.
// This is used for memory testing programs that pass options
- // via environment varaibles.
+ // via environment variables.
std::string memTesterEnvironmentVariable =
this->MemoryTesterEnvironmentVariable;
for (std::string const& arg : this->MemoryTesterOptions) {
@@ -408,8 +411,10 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Element("EndDateTime", this->EndTest);
xml.Element("EndTestTime", this->EndTestTime);
- xml.Element("ElapsedMinutes",
- static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+ xml.Element(
+ "ElapsedMinutes",
+ std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime)
+ .count());
xml.EndElement(); // DynamicAnalysis
this->CTest->EndXML(xml);
@@ -421,7 +426,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTester.clear();
// Setup the command
if (cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("MemoryCheckCommand").c_str())) {
+ this->CTest->GetCTestConfiguration("MemoryCheckCommand"))) {
this->MemoryTester =
this->CTest->GetCTestConfiguration("MemoryCheckCommand");
std::string testerName =
@@ -438,17 +443,15 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
this->MemoryTesterStyle = cmCTestMemCheckHandler::UNKNOWN;
}
} else if (cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("PurifyCommand").c_str())) {
+ this->CTest->GetCTestConfiguration("PurifyCommand"))) {
this->MemoryTester = this->CTest->GetCTestConfiguration("PurifyCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::PURIFY;
} else if (cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("ValgrindCommand")
- .c_str())) {
+ this->CTest->GetCTestConfiguration("ValgrindCommand"))) {
this->MemoryTester = this->CTest->GetCTestConfiguration("ValgrindCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::VALGRIND;
} else if (cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("BoundsCheckerCommand")
- .c_str())) {
+ this->CTest->GetCTestConfiguration("BoundsCheckerCommand"))) {
this->MemoryTester =
this->CTest->GetCTestConfiguration("BoundsCheckerCommand");
this->MemoryTesterStyle = cmCTestMemCheckHandler::BOUNDS_CHECKER;
@@ -532,9 +535,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
}
if (!this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
.empty()) {
- if (!cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
- .c_str())) {
+ if (!cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
+ "MemoryCheckSuppressionFile"))) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot find memory checker suppression file: "
<< this->CTest->GetCTestConfiguration(
@@ -542,12 +544,12 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
<< std::endl);
return false;
}
- std::string suppressions = "--suppressions=" +
- this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile");
- this->MemoryTesterOptions.push_back(suppressions);
+ this->MemoryTesterOptions.push_back(
+ "--suppressions=" +
+ this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile"));
}
- std::string outputFile = "--log-file=" + this->MemoryTesterOutputFile;
- this->MemoryTesterDynamicOptions.push_back(outputFile);
+ this->MemoryTesterDynamicOptions.push_back("--log-file=" +
+ this->MemoryTesterOutputFile);
break;
}
case cmCTestMemCheckHandler::PURIFY: {
@@ -555,9 +557,8 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
#ifdef _WIN32
if (this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
.size()) {
- if (!cmSystemTools::FileExists(
- this->CTest->GetCTestConfiguration("MemoryCheckSuppressionFile")
- .c_str())) {
+ if (!cmSystemTools::FileExists(this->CTest->GetCTestConfiguration(
+ "MemoryCheckSuppressionFile"))) {
cmCTestLog(
this->CTest, ERROR_MESSAGE,
"Cannot find memory checker suppression file: "
@@ -585,7 +586,7 @@ bool cmCTestMemCheckHandler::InitializeMemoryChecking()
"/Testing/Temporary/MemoryChecker.??.DPbd";
this->BoundsCheckerDPBDFile = dpbdFile;
this->MemoryTesterDynamicOptions.push_back("/B");
- this->MemoryTesterDynamicOptions.push_back(dpbdFile);
+ this->MemoryTesterDynamicOptions.push_back(std::move(dpbdFile));
this->MemoryTesterDynamicOptions.push_back("/X");
this->MemoryTesterDynamicOptions.push_back(this->MemoryTesterOutputFile);
this->MemoryTesterOptions.push_back("/M");
@@ -844,7 +845,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is "
"locked by a different thread");
std::vector<std::string::size_type> nonValGrindOutput;
- double sttime = cmSystemTools::GetTime();
+ auto sttime = std::chrono::steady_clock::now();
cmCTestOptionalLog(this->CTest, DEBUG,
"Start test: " << lines.size() << std::endl, this->Quiet);
std::string::size_type totalOutputSize = 0;
@@ -917,9 +918,11 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput(
break; // stop the copy of output if we are full
}
}
- cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
- << (cmSystemTools::GetTime() - sttime) << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, DEBUG, "End test (elapsed: "
+ << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
+ << "s)" << std::endl,
+ this->Quiet);
log = ostr.str();
this->DefectCount += defects;
return defects == 0;
@@ -929,7 +932,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
const std::string& str, std::string& log, std::vector<int>& results)
{
log.clear();
- double sttime = cmSystemTools::GetTime();
+ auto sttime = std::chrono::steady_clock::now();
std::vector<std::string> lines;
cmSystemTools::Split(str.c_str(), lines);
cmCTestOptionalLog(this->CTest, DEBUG,
@@ -960,9 +963,11 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput(
results[err]++;
defects++;
}
- cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: "
- << (cmSystemTools::GetTime() - sttime) << std::endl,
- this->Quiet);
+ cmCTestOptionalLog(
+ this->CTest, DEBUG, "End test (elapsed: "
+ << cmDurationTo<unsigned int>(std::chrono::steady_clock::now() - sttime)
+ << "s)" << std::endl,
+ this->Quiet);
if (defects) {
// only put the output of Bounds Checker if there were
// errors or leaks detected
@@ -1084,10 +1089,10 @@ void cmCTestMemCheckHandler::TestOutputFileNames(
files = g.GetFiles();
return;
}
- } else if (!cmSystemTools::FileExists(ofile.c_str())) {
+ } else if (!cmSystemTools::FileExists(ofile)) {
std::string log = "Cannot find memory tester output file: " + ofile;
cmCTestLog(this->CTest, ERROR_MESSAGE, log << std::endl);
ofile.clear();
}
- files.push_back(ofile);
+ files.push_back(std::move(ofile));
}
diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx
index 6a7bdc03e..50c2d86d7 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.cxx
+++ b/Source/CTest/cmCTestMultiProcessHandler.cxx
@@ -9,10 +9,16 @@
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
+#include "cm_uv.h"
+
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+
#include "cmsys/FStream.hxx"
#include "cmsys/String.hxx"
#include "cmsys/SystemInformation.hxx"
+
#include <algorithm>
+#include <chrono>
#include <iomanip>
#include <list>
#include <math.h>
@@ -95,24 +101,32 @@ void cmCTestMultiProcessHandler::RunTests()
if (this->HasCycles) {
return;
}
+#ifdef CMAKE_UV_SIGNAL_HACK
+ cmUVSignalHackRAII hackRAII;
+#endif
this->TestHandler->SetMaxIndex(this->FindMaxIndex());
+
+ uv_loop_init(&this->Loop);
this->StartNextTests();
- while (!this->Tests.empty()) {
- if (this->StopTimePassed) {
- return;
- }
- this->CheckOutput();
- this->StartNextTests();
- }
- // let all running tests finish
- while (this->CheckOutput()) {
- }
+ uv_run(&this->Loop, UV_RUN_DEFAULT);
+ uv_loop_close(&this->Loop);
+
this->MarkFinished();
this->UpdateCostData();
}
-void cmCTestMultiProcessHandler::StartTestProcess(int test)
+bool cmCTestMultiProcessHandler::StartTestProcess(int test)
{
+ std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime();
+ if (stop_time != std::chrono::system_clock::time_point() &&
+ stop_time <= std::chrono::system_clock::now()) {
+ cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. "
+ "Stopping all tests."
+ << std::endl);
+ this->StopTimePassed = true;
+ return false;
+ }
+
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
"test " << test << "\n", this->Quiet);
this->TestRunningMap[test] = true; // mark the test as running
@@ -120,7 +134,7 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
this->EraseTest(test);
this->RunningCount += GetProcessorsUsed(test);
- cmCTestRunTest* testRun = new cmCTestRunTest(this->TestHandler);
+ cmCTestRunTest* testRun = new cmCTestRunTest(*this);
if (this->CTest->GetRepeatUntilFail()) {
testRun->SetRunUntilFailOn();
testRun->SetNumberOfRuns(this->CTest->GetTestRepeat());
@@ -143,28 +157,11 @@ void cmCTestMultiProcessHandler::StartTestProcess(int test)
this->LockResources(test);
if (testRun->StartTest(this->Total)) {
- this->RunningTests.insert(testRun);
- } else if (testRun->IsStopTimePassed()) {
- this->StopTimePassed = true;
- delete testRun;
- return;
- } else {
-
- for (auto& j : this->Tests) {
- j.second.erase(test);
- }
-
- this->UnlockResources(test);
- this->Completed++;
- this->TestFinishMap[test] = true;
- this->TestRunningMap[test] = false;
- this->RunningCount -= GetProcessorsUsed(test);
- testRun->EndTest(this->Completed, this->Total, false);
- if (!this->Properties[test]->Disabled) {
- this->Failed->push_back(this->Properties[test]->Name);
- }
- delete testRun;
+ return true;
}
+
+ this->FinishTestProcess(testRun, false);
+ return false;
}
void cmCTestMultiProcessHandler::LockResources(int index)
@@ -222,8 +219,7 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
// if there are no depends left then run this test
if (this->Tests[test].empty()) {
- this->StartTestProcess(test);
- return true;
+ return this->StartTestProcess(test);
}
// This test was not able to start because it is waiting
// on depends to run
@@ -233,6 +229,11 @@ bool cmCTestMultiProcessHandler::StartTest(int test)
void cmCTestMultiProcessHandler::StartNextTests()
{
size_t numToStart = 0;
+
+ if (this->Tests.empty()) {
+ return;
+ }
+
if (this->RunningCount < this->ParallelLevel) {
numToStart = this->ParallelLevel - this->RunningCount;
}
@@ -326,10 +327,22 @@ void cmCTestMultiProcessHandler::StartNextTests()
}
if (allTestsFailedTestLoadCheck) {
+ // Find out whether there are any non RUN_SERIAL tests left, so that the
+ // correct warning may be displayed.
+ bool onlyRunSerialTestsLeft = true;
+ for (auto const& test : copy) {
+ if (!this->Properties[test]->RunSerial) {
+ onlyRunSerialTestsLeft = false;
+ }
+ }
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, ");
+
if (this->SerialTestRunning) {
cmCTestLog(this->CTest, HANDLER_OUTPUT,
"Waiting for RUN_SERIAL test to finish.");
+ } else if (onlyRunSerialTestsLeft) {
+ cmCTestLog(this->CTest, HANDLER_OUTPUT,
+ "Only RUN_SERIAL tests remain, awaiting available slot.");
} else {
/* clang-format off */
cmCTestLog(this->CTest, HANDLER_OUTPUT,
@@ -353,45 +366,42 @@ void cmCTestMultiProcessHandler::StartNextTests()
}
}
-bool cmCTestMultiProcessHandler::CheckOutput()
+void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner,
+ bool started)
{
- // no more output we are done
- if (this->RunningTests.empty()) {
- return false;
- }
- std::vector<cmCTestRunTest*> finished;
- std::string out, err;
- for (cmCTestRunTest* p : this->RunningTests) {
- if (!p->CheckOutput()) {
- finished.push_back(p);
- }
- }
- for (cmCTestRunTest* p : finished) {
- this->Completed++;
- int test = p->GetIndex();
+ this->Completed++;
+
+ int test = runner->GetIndex();
+ auto properties = runner->GetTestProperties();
- bool testResult = p->EndTest(this->Completed, this->Total, true);
- if (p->StartAgain()) {
+ bool testResult = runner->EndTest(this->Completed, this->Total, started);
+ if (started) {
+ if (runner->StartAgain()) {
this->Completed--; // remove the completed test because run again
- continue;
- }
- if (testResult) {
- this->Passed->push_back(p->GetTestProperties()->Name);
- } else {
- this->Failed->push_back(p->GetTestProperties()->Name);
- }
- for (auto& t : this->Tests) {
- t.second.erase(test);
+ return;
}
- this->TestFinishMap[test] = true;
- this->TestRunningMap[test] = false;
- this->RunningTests.erase(p);
- this->WriteCheckpoint(test);
- this->UnlockResources(test);
- this->RunningCount -= GetProcessorsUsed(test);
- delete p;
}
- return true;
+
+ if (testResult) {
+ this->Passed->push_back(properties->Name);
+ } else if (!properties->Disabled) {
+ this->Failed->push_back(properties->Name);
+ }
+
+ for (auto& t : this->Tests) {
+ t.second.erase(test);
+ }
+
+ this->TestFinishMap[test] = true;
+ this->TestRunningMap[test] = false;
+ this->WriteCheckpoint(test);
+ this->UnlockResources(test);
+ this->RunningCount -= GetProcessorsUsed(test);
+
+ delete runner;
+ if (started) {
+ this->StartNextTests();
+ }
}
void cmCTestMultiProcessHandler::UpdateCostData()
@@ -403,7 +413,7 @@ void cmCTestMultiProcessHandler::UpdateCostData()
PropertiesMap temp = this->Properties;
- if (cmSystemTools::FileExists(fname.c_str())) {
+ if (cmSystemTools::FileExists(fname)) {
cmsys::ifstream fin;
fin.open(fname.c_str());
@@ -456,7 +466,7 @@ void cmCTestMultiProcessHandler::ReadCostData()
{
std::string fname = this->CTest->GetCostDataFile();
- if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ if (cmSystemTools::FileExists(fname, true)) {
cmsys::ifstream fin;
fin.open(fname.c_str());
std::string line;
@@ -525,7 +535,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList()
TestSet alreadySortedTests;
std::list<TestSet> priorityStack;
- priorityStack.push_back(TestSet());
+ priorityStack.emplace_back();
TestSet& topLevel = priorityStack.back();
// In parallel test runs add previously failed tests to the front
@@ -547,7 +557,7 @@ void cmCTestMultiProcessHandler::CreateParallelTestCostList()
// further dependencies exist.
while (!priorityStack.back().empty()) {
TestSet& previousSet = priorityStack.back();
- priorityStack.push_back(TestSet());
+ priorityStack.emplace_back();
TestSet& currentSet = priorityStack.back();
for (auto const& i : previousSet) {
@@ -658,7 +668,7 @@ void cmCTestMultiProcessHandler::PrintTestList()
cmWorkingDirectory workdir(p.Directory);
- cmCTestRunTest testRun(this->TestHandler);
+ cmCTestRunTest testRun(*this);
testRun.SetIndex(p.Index);
testRun.SetTestProperties(&p);
testRun.ComputeArguments(); // logs the command in verbose mode
@@ -731,7 +741,7 @@ void cmCTestMultiProcessHandler::CheckResume()
std::string fname =
this->CTest->GetBinaryDir() + "/Testing/Temporary/CTestCheckpoint.txt";
if (this->CTest->GetFailover()) {
- if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ if (cmSystemTools::FileExists(fname, true)) {
*this->TestHandler->LogFile
<< "Resuming previously interrupted test set" << std::endl
<< "----------------------------------------------------------"
@@ -746,7 +756,7 @@ void cmCTestMultiProcessHandler::CheckResume()
}
fin.close();
}
- } else if (cmSystemTools::FileExists(fname.c_str(), true)) {
+ } else if (cmSystemTools::FileExists(fname, true)) {
cmSystemTools::RemoveFile(fname);
}
}
diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h
index dccc2c896..7837ff910 100644
--- a/Source/CTest/cmCTestMultiProcessHandler.h
+++ b/Source/CTest/cmCTestMultiProcessHandler.h
@@ -12,6 +12,8 @@
#include <string>
#include <vector>
+#include "cm_uv.h"
+
class cmCTest;
class cmCTestRunTest;
@@ -23,6 +25,7 @@ class cmCTestRunTest;
class cmCTestMultiProcessHandler
{
friend class TestComparator;
+ friend class cmCTestRunTest;
public:
struct TestSet : public std::set<int>
@@ -75,7 +78,7 @@ protected:
// Start the next test or tests as many as are allowed by
// ParallelLevel
void StartNextTests();
- void StartTestProcess(int test);
+ bool StartTestProcess(int test);
bool StartTest(int test);
// Mark the checkpoint for the given test
void WriteCheckpoint(int index);
@@ -95,9 +98,8 @@ protected:
// Removes the checkpoint file
void MarkFinished();
void EraseTest(int index);
- // Return true if there are still tests running
- // check all running processes for output and exit case
- bool CheckOutput();
+ void FinishTestProcess(cmCTestRunTest* runner, bool started);
+
void RemoveTest(int index);
// Check if we need to resume an interrupted test set
void CheckResume();
@@ -130,7 +132,7 @@ protected:
std::vector<cmCTestTestHandler::cmCTestTestResult>* TestResults;
size_t ParallelLevel; // max number of process that can be run at once
unsigned long TestLoad;
- std::set<cmCTestRunTest*> RunningTests; // current running tests
+ uv_loop_t Loop;
cmCTestTestHandler* TestHandler;
cmCTest* CTest;
bool HasCycles;
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index abdb6433f..30ad38ca1 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -4,28 +4,28 @@
#include "cmCTest.h"
#include "cmCTestMemCheckHandler.h"
-#include "cmCTestTestHandler.h"
+#include "cmCTestMultiProcessHandler.h"
#include "cmProcess.h"
#include "cmSystemTools.h"
#include "cmWorkingDirectory.h"
-#include "cm_curl.h"
#include "cm_zlib.h"
#include "cmsys/Base64.h"
-#include "cmsys/Process.h"
#include "cmsys/RegularExpression.hxx"
+#include <chrono>
+#include <cmAlgorithms.h>
#include <iomanip>
+#include <ratio>
#include <sstream>
#include <stdio.h>
-#include <time.h>
#include <utility>
-cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
+cmCTestRunTest::cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler)
+ : MultiTestHandler(multiHandler)
{
- this->CTest = handler->CTest;
- this->TestHandler = handler;
- this->TestProcess = nullptr;
- this->TestResult.ExecutionTime = 0;
+ this->CTest = multiHandler.CTest;
+ this->TestHandler = multiHandler.TestHandler;
+ this->TestResult.ExecutionTime = cmDuration::zero();
this->TestResult.ReturnValue = 0;
this->TestResult.Status = cmCTestTestHandler::NOT_RUN;
this->TestResult.TestCount = 0;
@@ -33,57 +33,37 @@ cmCTestRunTest::cmCTestRunTest(cmCTestTestHandler* handler)
this->ProcessOutput.clear();
this->CompressedOutput.clear();
this->CompressionRatio = 2;
- this->StopTimePassed = false;
this->NumberOfRunsLeft = 1; // default to 1 run of the test
this->RunUntilFail = false; // default to run the test once
this->RunAgain = false; // default to not having to run again
}
-cmCTestRunTest::~cmCTestRunTest()
+void cmCTestRunTest::CheckOutput(std::string const& line)
{
-}
-
-bool cmCTestRunTest::CheckOutput()
-{
- // Read lines for up to 0.1 seconds of total time.
- double timeout = 0.1;
- double timeEnd = cmSystemTools::GetTime() + timeout;
- std::string line;
- while ((timeout = timeEnd - cmSystemTools::GetTime(), timeout > 0)) {
- int p = this->TestProcess->GetNextOutputLine(line, timeout);
- if (p == cmsysProcess_Pipe_None) {
- // Process has terminated and all output read.
- return false;
- }
- if (p == cmsysProcess_Pipe_STDOUT) {
- // Store this line of output.
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
- << ": " << line << std::endl);
- this->ProcessOutput += line;
- this->ProcessOutput += "\n";
-
- // Check for TIMEOUT_AFTER_MATCH property.
- if (!this->TestProperties->TimeoutRegularExpressions.empty()) {
- for (auto& reg : this->TestProperties->TimeoutRegularExpressions) {
- if (reg.first.find(this->ProcessOutput.c_str())) {
- cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
- << ": "
- << "Test timeout changed to "
- << this->TestProperties->AlternateTimeout
- << std::endl);
- this->TestProcess->ResetStartTime();
- this->TestProcess->ChangeTimeout(
- this->TestProperties->AlternateTimeout);
- this->TestProperties->TimeoutRegularExpressions.clear();
- break;
- }
- }
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
+ << ": " << line << std::endl);
+ this->ProcessOutput += line;
+ this->ProcessOutput += "\n";
+
+ // Check for TIMEOUT_AFTER_MATCH property.
+ if (!this->TestProperties->TimeoutRegularExpressions.empty()) {
+ for (auto& reg : this->TestProperties->TimeoutRegularExpressions) {
+ if (reg.first.find(this->ProcessOutput.c_str())) {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->GetIndex()
+ << ": "
+ << "Test timeout changed to "
+ << std::chrono::duration_cast<std::chrono::seconds>(
+ this->TestProperties->AlternateTimeout)
+ .count()
+ << std::endl);
+ this->TestProcess->ResetStartTime();
+ this->TestProcess->ChangeTimeout(
+ this->TestProperties->AlternateTimeout);
+ this->TestProperties->TimeoutRegularExpressions.clear();
+ break;
}
- } else { // if(p == cmsysProcess_Pipe_Timeout)
- break;
}
}
- return true;
}
// Streamed compression of test output. The compressed data
@@ -156,8 +136,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
this->WriteLogOutputTop(completed, total);
std::string reason;
bool passed = true;
- int res =
- started ? this->TestProcess->GetProcessStatus() : cmsysProcess_State_Error;
+ cmProcess::State res =
+ started ? this->TestProcess->GetProcessStatus() : cmProcess::State::Error;
int retVal = this->TestProcess->GetExitValue();
bool forceFail = false;
bool skipped = false;
@@ -196,7 +176,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
}
}
}
- if (res == cmsysProcess_State_Exited) {
+ if (res == cmProcess::State::Exited) {
bool success = !forceFail &&
(retVal == 0 ||
!this->TestProperties->RequiredRegularExpressions.empty());
@@ -217,29 +197,29 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Failed " << reason);
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
}
- } else if (res == cmsysProcess_State_Expired) {
+ } else if (res == cmProcess::State::Expired) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Timeout ");
this->TestResult.Status = cmCTestTestHandler::TIMEOUT;
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
- } else if (res == cmsysProcess_State_Exception) {
+ } else if (res == cmProcess::State::Exception) {
outputTestErrorsToConsole = this->CTest->OutputTestOutputOnTestFailure;
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Exception: ");
this->TestResult.ExceptionStatus =
this->TestProcess->GetExitExceptionString();
switch (this->TestProcess->GetExitException()) {
- case cmsysProcess_Exception_Fault:
+ case cmProcess::Exception::Fault:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "SegFault");
this->TestResult.Status = cmCTestTestHandler::SEGFAULT;
break;
- case cmsysProcess_Exception_Illegal:
+ case cmProcess::Exception::Illegal:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Illegal");
this->TestResult.Status = cmCTestTestHandler::ILLEGAL;
break;
- case cmsysProcess_Exception_Interrupt:
+ case cmProcess::Exception::Interrupt:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Interrupt");
this->TestResult.Status = cmCTestTestHandler::INTERRUPT;
break;
- case cmsysProcess_Exception_Numerical:
+ case cmProcess::Exception::Numerical:
cmCTestLog(this->CTest, HANDLER_OUTPUT, "Numerical");
this->TestResult.Status = cmCTestTestHandler::NUMERICAL;
break;
@@ -250,14 +230,14 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
}
} else if ("Disabled" == this->TestResult.CompletionStatus) {
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run (Disabled) ");
- } else // cmsysProcess_State_Error
+ } else // cmProcess::State::Error
{
cmCTestLog(this->CTest, HANDLER_OUTPUT, "***Not Run ");
}
passed = this->TestResult.Status == cmCTestTestHandler::COMPLETED;
char buf[1024];
- sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime());
+ sprintf(buf, "%6.2f sec", this->TestProcess->GetTotalTime().count());
cmCTestLog(this->CTest, HANDLER_OUTPUT, buf << "\n");
if (outputTestErrorsToConsole) {
@@ -293,12 +273,16 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
reasonType = "Test Fail Reason";
pass = false;
}
- double ttime = this->TestProcess->GetTotalTime();
- int hours = static_cast<int>(ttime / (60 * 60));
- int minutes = static_cast<int>(ttime / 60) % 60;
- int seconds = static_cast<int>(ttime) % 60;
+ auto ttime = this->TestProcess->GetTotalTime();
+ auto hours = std::chrono::duration_cast<std::chrono::hours>(ttime);
+ ttime -= hours;
+ auto minutes = std::chrono::duration_cast<std::chrono::minutes>(ttime);
+ ttime -= minutes;
+ auto seconds = std::chrono::duration_cast<std::chrono::seconds>(ttime);
char buffer[100];
- sprintf(buffer, "%02d:%02d:%02d", hours, minutes, seconds);
+ sprintf(buffer, "%02d:%02d:%02d", static_cast<unsigned>(hours.count()),
+ static_cast<unsigned>(minutes.count()),
+ static_cast<unsigned>(seconds.count()));
*this->TestHandler->LogFile
<< "----------------------------------------------------------"
<< std::endl;
@@ -342,7 +326,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
if (!this->NeedsToRerun()) {
this->TestHandler->TestResults.push_back(this->TestResult);
}
- delete this->TestProcess;
+ this->TestProcess.reset();
return passed || skipped;
}
@@ -378,7 +362,7 @@ void cmCTestRunTest::ComputeWeightedCost()
{
double prev = static_cast<double>(this->TestProperties->PreviousRuns);
double avgcost = static_cast<double>(this->TestProperties->Cost);
- double current = this->TestResult.ExecutionTime;
+ double current = this->TestResult.ExecutionTime.count();
if (this->TestResult.Status == cmCTestTestHandler::COMPLETED) {
this->TestProperties->Cost =
@@ -416,7 +400,7 @@ bool cmCTestRunTest::StartTest(size_t total)
// Return immediately if test is disabled
if (this->TestProperties->Disabled) {
this->TestResult.Properties = this->TestProperties;
- this->TestResult.ExecutionTime = 0;
+ this->TestResult.ExecutionTime = cmDuration::zero();
this->TestResult.CompressOutput = false;
this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Disabled";
@@ -424,16 +408,14 @@ bool cmCTestRunTest::StartTest(size_t total)
this->TestResult.TestCount = this->TestProperties->Index;
this->TestResult.Name = this->TestProperties->Name;
this->TestResult.Path = this->TestProperties->Directory;
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestResult.Output = "Disabled";
this->TestResult.FullCommandLine.clear();
return false;
}
- this->ComputeArguments();
- std::vector<std::string>& args = this->TestProperties->Args;
this->TestResult.Properties = this->TestProperties;
- this->TestResult.ExecutionTime = 0;
+ this->TestResult.ExecutionTime = cmDuration::zero();
this->TestResult.CompressOutput = false;
this->TestResult.ReturnValue = -1;
this->TestResult.CompletionStatus = "Failed to start";
@@ -442,8 +424,12 @@ bool cmCTestRunTest::StartTest(size_t total)
this->TestResult.Name = this->TestProperties->Name;
this->TestResult.Path = this->TestProperties->Directory;
+ // Check for failed fixture dependencies before we even look at the command
+ // arguments because if we are not going to run the test, the command and
+ // its arguments are irrelevant. This matters for the case where a fixture
+ // dependency might be creating the executable we want to run.
if (!this->FailedDependencies.empty()) {
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
std::string msg = "Failed test dependencies:";
for (std::string const& failedDep : this->FailedDependencies) {
msg += " " + failedDep;
@@ -457,8 +443,10 @@ bool cmCTestRunTest::StartTest(size_t total)
return false;
}
+ this->ComputeArguments();
+ std::vector<std::string>& args = this->TestProperties->Args;
if (args.size() >= 2 && args[1] == "NOT_AVAILABLE") {
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
std::string msg;
if (this->CTest->GetConfigType().empty()) {
msg = "Test not available without configuration.";
@@ -479,9 +467,9 @@ bool cmCTestRunTest::StartTest(size_t total)
// Check if all required files exist
for (std::string const& file : this->TestProperties->RequiredFiles) {
- if (!cmSystemTools::FileExists(file.c_str())) {
+ if (!cmSystemTools::FileExists(file)) {
// Required file was not found
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
*this->TestHandler->LogFile << "Unable to find required file: " << file
<< std::endl;
cmCTestLog(this->CTest, ERROR_MESSAGE,
@@ -497,7 +485,7 @@ bool cmCTestRunTest::StartTest(size_t total)
if (this->ActualCommand.empty()) {
// if the command was not found create a TestResult object
// that has that information
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
*this->TestHandler->LogFile << "Unable to find executable: " << args[1]
<< std::endl;
cmCTestLog(this->CTest, ERROR_MESSAGE,
@@ -510,11 +498,22 @@ bool cmCTestRunTest::StartTest(size_t total)
}
this->StartTime = this->CTest->CurrentTime();
- double timeout = this->ResolveTimeout();
+ auto timeout = this->TestProperties->Timeout;
- if (this->StopTimePassed) {
- return false;
+ std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime();
+ if (stop_time != std::chrono::system_clock::time_point()) {
+ std::chrono::duration<double> stop_timeout =
+ (stop_time - std::chrono::system_clock::now()) % std::chrono::hours(24);
+
+ if (stop_timeout <= std::chrono::duration<double>::zero()) {
+ stop_timeout = std::chrono::duration<double>::zero();
+ }
+ if (timeout == std::chrono::duration<double>::zero() ||
+ stop_timeout < timeout) {
+ timeout = stop_timeout;
+ }
}
+
return this->ForkProcess(timeout, this->TestProperties->ExplicitTimeout,
&this->TestProperties->Environment);
}
@@ -538,7 +537,7 @@ void cmCTestRunTest::ComputeArguments()
++j; // skip the executable (it will be actualCommand)
}
std::string testCommand =
- cmSystemTools::ConvertToOutputPath(this->ActualCommand.c_str());
+ cmSystemTools::ConvertToOutputPath(this->ActualCommand);
// Prepends memcheck args to our command string
this->TestHandler->GenerateTestCommand(this->Arguments, this->Index);
@@ -591,66 +590,10 @@ void cmCTestRunTest::DartProcessing()
}
}
-double cmCTestRunTest::ResolveTimeout()
-{
- double timeout = this->TestProperties->Timeout;
-
- if (this->CTest->GetStopTime().empty()) {
- return timeout;
- }
- struct tm* lctime;
- time_t current_time = time(nullptr);
- lctime = gmtime(&current_time);
- int gm_hour = lctime->tm_hour;
- time_t gm_time = mktime(lctime);
- lctime = localtime(&current_time);
- int local_hour = lctime->tm_hour;
-
- int tzone_offset = local_hour - gm_hour;
- if (gm_time > current_time && gm_hour < local_hour) {
- // this means gm_time is on the next day
- tzone_offset -= 24;
- } else if (gm_time < current_time && gm_hour > local_hour) {
- // this means gm_time is on the previous day
- tzone_offset += 24;
- }
-
- tzone_offset *= 100;
- char buf[1024];
- // add todays year day and month to the time in str because
- // curl_getdate no longer assumes the day is today
- sprintf(buf, "%d%02d%02d %s %+05i", lctime->tm_year + 1900,
- lctime->tm_mon + 1, lctime->tm_mday,
- this->CTest->GetStopTime().c_str(), tzone_offset);
-
- time_t stop_time = curl_getdate(buf, &current_time);
- if (stop_time == -1) {
- return timeout;
- }
-
- // the stop time refers to the next day
- if (this->CTest->NextDayStopTime) {
- stop_time += 24 * 60 * 60;
- }
- int stop_timeout =
- static_cast<int>(stop_time - current_time) % (24 * 60 * 60);
- this->CTest->LastStopTimeout = stop_timeout;
-
- if (stop_timeout <= 0 || stop_timeout > this->CTest->LastStopTimeout) {
- cmCTestLog(this->CTest, ERROR_MESSAGE, "The stop time has been passed. "
- "Stopping all tests."
- << std::endl);
- this->StopTimePassed = true;
- return 0;
- }
- return timeout == 0 ? stop_timeout
- : (timeout < stop_timeout ? timeout : stop_timeout);
-}
-
-bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
+bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
std::vector<std::string>* environment)
{
- this->TestProcess = new cmProcess;
+ this->TestProcess = cm::make_unique<cmProcess>(*this);
this->TestProcess->SetId(this->Index);
this->TestProcess->SetWorkingDirectory(
this->TestProperties->Directory.c_str());
@@ -658,25 +601,30 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
this->TestProcess->SetCommandArguments(this->Arguments);
// determine how much time we have
- double timeout = this->CTest->GetRemainingTimeAllowed() - 120;
- if (this->CTest->GetTimeOut() > 0 && this->CTest->GetTimeOut() < timeout) {
+ cmDuration timeout = this->CTest->GetRemainingTimeAllowed();
+ if (timeout != cmCTest::MaxDuration()) {
+ timeout -= std::chrono::minutes(2);
+ }
+ if (this->CTest->GetTimeOut() > cmDuration::zero() &&
+ this->CTest->GetTimeOut() < timeout) {
timeout = this->CTest->GetTimeOut();
}
- if (testTimeOut > 0 &&
+ if (testTimeOut > cmDuration::zero() &&
testTimeOut < this->CTest->GetRemainingTimeAllowed()) {
timeout = testTimeOut;
}
// always have at least 1 second if we got to here
- if (timeout <= 0) {
- timeout = 1;
+ if (timeout <= cmDuration::zero()) {
+ timeout = std::chrono::seconds(1);
}
// handle timeout explicitly set to 0
- if (testTimeOut == 0 && explicitTimeout) {
- timeout = 0;
+ if (testTimeOut == cmDuration::zero() && explicitTimeout) {
+ timeout = cmDuration::zero();
}
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index
<< ": "
- << "Test timeout computed to be: " << timeout << "\n",
+ << "Test timeout computed to be: "
+ << cmDurationTo<unsigned int>(timeout) << "\n",
this->TestHandler->GetQuiet());
this->TestProcess->SetTimeout(timeout);
@@ -689,7 +637,7 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
cmSystemTools::AppendEnv(*environment);
}
- return this->TestProcess->StartProcess();
+ return this->TestProcess->StartProcess(this->MultiTestHandler.Loop);
}
void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
@@ -763,3 +711,8 @@ void cmCTestRunTest::WriteLogOutputTop(size_t completed, size_t total)
cmCTestLog(this->CTest, DEBUG, "Testing " << this->TestProperties->Name
<< " ... ");
}
+
+void cmCTestRunTest::FinalizeTest()
+{
+ this->MultiTestHandler.FinishTestProcess(this, true);
+}
diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h
index d3bb2296f..4d573572f 100644
--- a/Source/CTest/cmCTestRunTest.h
+++ b/Source/CTest/cmCTestRunTest.h
@@ -11,9 +11,11 @@
#include <vector>
#include "cmCTestTestHandler.h"
+#include "cmDuration.h"
+#include "cmProcess.h" // IWYU pragma: keep (for unique_ptr)
class cmCTest;
-class cmProcess;
+class cmCTestMultiProcessHandler;
/** \class cmRunTest
* \brief represents a single test to be run
@@ -23,8 +25,9 @@ class cmProcess;
class cmCTestRunTest
{
public:
- cmCTestRunTest(cmCTestTestHandler* handler);
- ~cmCTestRunTest();
+ explicit cmCTestRunTest(cmCTestMultiProcessHandler& multiHandler);
+
+ ~cmCTestRunTest() = default;
void SetNumberOfRuns(int n) { this->NumberOfRunsLeft = n; }
void SetRunUntilFailOn() { this->RunUntilFail = true; }
@@ -49,15 +52,13 @@ public:
std::string GetProcessOutput() { return this->ProcessOutput; }
- bool IsStopTimePassed() { return this->StopTimePassed; }
-
cmCTestTestHandler::cmCTestTestResult GetTestResults()
{
return this->TestResult;
}
// Read and store output. Returns true if it must be called again.
- bool CheckOutput();
+ void CheckOutput(std::string const& line);
// Compresses the output, writing to CompressedOutput
void CompressOutput();
@@ -73,13 +74,15 @@ public:
bool StartAgain();
+ cmCTest* GetCTest() const { return this->CTest; }
+
+ void FinalizeTest();
+
private:
bool NeedsToRerun();
void DartProcessing();
void ExeNotFound(std::string exe);
- // Figures out a final timeout which is min(STOP_TIME, NOW+TIMEOUT)
- double ResolveTimeout();
- bool ForkProcess(double testTimeOut, bool explicitTimeout,
+ bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout,
std::vector<std::string>* environment);
void WriteLogOutputTop(size_t completed, size_t total);
// Run post processing of the process output for MemCheck
@@ -89,26 +92,18 @@ private:
// Pointer back to the "parent"; the handler that invoked this test run
cmCTestTestHandler* TestHandler;
cmCTest* CTest;
- cmProcess* TestProcess;
- // If the executable to run is ctest, don't create a new process;
- // just instantiate a new cmTest. (Can be disabled for a single test
- // if this option is set to false.)
- // bool OptimizeForCTest;
-
- bool UsePrefixCommand;
- std::string PrefixCommand;
-
+ std::unique_ptr<cmProcess> TestProcess;
std::string ProcessOutput;
std::string CompressedOutput;
double CompressionRatio;
// The test results
cmCTestTestHandler::cmCTestTestResult TestResult;
+ cmCTestMultiProcessHandler& MultiTestHandler;
int Index;
std::set<std::string> FailedDependencies;
std::string StartTime;
std::string ActualCommand;
std::vector<std::string> Arguments;
- bool StopTimePassed;
bool RunUntilFail;
int NumberOfRunsLeft;
bool RunAgain;
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index ce9622492..73184fc05 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -515,7 +515,7 @@ private:
} else {
local_path = path;
}
- this->SVN->Repositories.push_back(SVNInfo(local_path.c_str()));
+ this->SVN->Repositories.emplace_back(local_path.c_str());
}
};
@@ -526,7 +526,7 @@ bool cmCTestSVN::LoadRepositories()
}
// Info for root repository
- this->Repositories.push_back(SVNInfo(""));
+ this->Repositories.emplace_back("");
this->RootInfo = &(this->Repositories.back());
// Run "svn status" to get the list of external repositories
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index dbc7fdef6..a467ede28 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -8,6 +8,7 @@
#include "cmCTestGlobalVC.h"
#include <iosfwd>
+#include <list>
#include <string>
#include <vector>
@@ -70,7 +71,8 @@ private:
friend struct Revision;
// Info of all the repositories (root, externals and nested ones).
- std::vector<SVNInfo> Repositories;
+ // Use std::list so the elements don't move in memory.
+ std::list<SVNInfo> Repositories;
// Pointer to the infos of the root repository.
SVNInfo* RootInfo;
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index fdd9622af..e0bffd476 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -5,6 +5,7 @@
#include "cmsys/Directory.hxx"
#include "cmsys/Process.h"
#include <map>
+#include <ratio>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
@@ -26,6 +27,7 @@
#include "cmCTestTestCommand.h"
#include "cmCTestUpdateCommand.h"
#include "cmCTestUploadCommand.h"
+#include "cmDuration.h"
#include "cmFunctionBlocker.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
@@ -79,9 +81,9 @@ cmCTestScriptHandler::cmCTestScriptHandler()
this->CMake = nullptr;
this->GlobalGenerator = nullptr;
- this->ScriptStartTime = 0;
+ this->ScriptStartTime = std::chrono::steady_clock::time_point();
- // the *60 is becuase the settings are in minutes but GetTime is seconds
+ // the *60 is because the settings are in minutes but GetTime is seconds
this->MinimumInterval = 30 * 60;
this->ContinuousDuration = -1;
}
@@ -111,7 +113,7 @@ void cmCTestScriptHandler::Initialize()
this->ContinuousDuration = -1;
// what time in seconds did this script start running
- this->ScriptStartTime = 0;
+ this->ScriptStartTime = std::chrono::steady_clock::time_point();
delete this->Makefile;
this->Makefile = nullptr;
@@ -158,11 +160,10 @@ void cmCTestScriptHandler::UpdateElapsedTime()
{
if (this->Makefile) {
// set the current elapsed time
- char timeString[20];
- int itime = static_cast<unsigned int>(cmSystemTools::GetTime() -
- this->ScriptStartTime);
- sprintf(timeString, "%i", itime);
- this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString);
+ auto itime = cmDurationTo<unsigned int>(std::chrono::steady_clock::now() -
+ this->ScriptStartTime);
+ auto timeString = std::to_string(itime);
+ this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str());
}
}
@@ -206,7 +207,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
std::vector<char> out;
std::vector<char> err;
std::string line;
- int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
+ int pipe =
+ cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
while (pipe != cmsysProcess_Pipe_None) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Output: " << line
<< "\n");
@@ -215,7 +217,8 @@ int cmCTestScriptHandler::ExecuteScript(const std::string& total_script_arg)
} else if (pipe == cmsysProcess_Pipe_STDOUT) {
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, line << "\n");
}
- pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+ pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
+ err);
}
// Properly handle output of the build command
@@ -324,7 +327,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
script_arg = total_script_arg.substr(comma_pos + 1);
}
// make sure the file exists
- if (!cmSystemTools::FileExists(script.c_str())) {
+ if (!cmSystemTools::FileExists(script)) {
cmSystemTools::Error("Cannot find file: ", script.c_str());
return 1;
}
@@ -343,6 +346,7 @@ int cmCTestScriptHandler::ReadInScript(const std::string& total_script_arg)
this->Makefile->AddDefinition("CMAKE_EXECUTABLE_NAME",
cmSystemTools::GetCMakeCommand().c_str());
this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", true);
+ this->SetRunCurrentScript(true);
this->UpdateElapsedTime();
// add the script arg if defined
@@ -507,7 +511,7 @@ int cmCTestScriptHandler::RunConfigurationScript(
int result;
- this->ScriptStartTime = cmSystemTools::GetTime();
+ this->ScriptStartTime = std::chrono::steady_clock::now();
// read in the script
if (pscope) {
@@ -524,7 +528,8 @@ int cmCTestScriptHandler::RunConfigurationScript(
}
// only run the curent script if we should
- if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT")) {
+ if (this->Makefile && this->Makefile->IsOn("CTEST_RUN_CURRENT_SCRIPT") &&
+ this->ShouldRunCurrentScript) {
return this->RunCurrentScript();
}
return result;
@@ -535,7 +540,7 @@ int cmCTestScriptHandler::RunCurrentScript()
int result;
// do not run twice
- this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", false);
+ this->SetRunCurrentScript(false);
// no popup widows
cmSystemTools::SetRunCommandHideConsole(true);
@@ -558,22 +563,25 @@ int cmCTestScriptHandler::RunCurrentScript()
// for a continuous, do we ned to run it more than once?
if (this->ContinuousDuration >= 0) {
this->UpdateElapsedTime();
- double ending_time = cmSystemTools::GetTime() + this->ContinuousDuration;
+ auto ending_time =
+ std::chrono::steady_clock::now() + cmDuration(this->ContinuousDuration);
if (this->EmptyBinDirOnce) {
this->EmptyBinDir = true;
}
do {
- double interval = cmSystemTools::GetTime();
+ auto startOfInterval = std::chrono::steady_clock::now();
result = this->RunConfigurationDashboard();
- interval = cmSystemTools::GetTime() - interval;
- if (interval < this->MinimumInterval) {
- this->SleepInSeconds(
- static_cast<unsigned int>(this->MinimumInterval - interval));
+ auto interval = std::chrono::steady_clock::now() - startOfInterval;
+ auto minimumInterval = cmDuration(this->MinimumInterval);
+ if (interval < minimumInterval) {
+ auto sleepTime =
+ cmDurationTo<unsigned int>(minimumInterval - interval);
+ this->SleepInSeconds(sleepTime);
}
if (this->EmptyBinDirOnce) {
this->EmptyBinDir = false;
}
- } while (cmSystemTools::GetTime() < ending_time);
+ } while (std::chrono::steady_clock::now() < ending_time);
}
// otherwise just run it once
else {
@@ -590,7 +598,7 @@ int cmCTestScriptHandler::CheckOutSourceDir()
int retVal;
bool res;
- if (!cmSystemTools::FileExists(this->SourceDir.c_str()) &&
+ if (!cmSystemTools::FileExists(this->SourceDir) &&
!this->CVSCheckOut.empty()) {
// we must now checkout the src dir
output.clear();
@@ -598,7 +606,8 @@ int cmCTestScriptHandler::CheckOutSourceDir()
"Run cvs: " << this->CVSCheckOut << std::endl);
res = cmSystemTools::RunSingleCommand(
this->CVSCheckOut.c_str(), &output, &output, &retVal,
- this->CTestRoot.c_str(), this->HandlerVerbose, 0 /*this->TimeOut*/);
+ this->CTestRoot.c_str(), this->HandlerVerbose,
+ cmDuration::zero() /*this->TimeOut*/);
if (!res || retVal != 0) {
cmSystemTools::Error("Unable to perform cvs checkout:\n",
output.c_str());
@@ -621,10 +630,10 @@ int cmCTestScriptHandler::BackupDirectories()
// backup the binary and src directories if requested
if (this->Backup) {
// if for some reason those directories exist then first delete them
- if (cmSystemTools::FileExists(this->BackupSourceDir.c_str())) {
+ if (cmSystemTools::FileExists(this->BackupSourceDir)) {
cmSystemTools::RemoveADirectory(this->BackupSourceDir);
}
- if (cmSystemTools::FileExists(this->BackupBinaryDir.c_str())) {
+ if (cmSystemTools::FileExists(this->BackupBinaryDir)) {
cmSystemTools::RemoveADirectory(this->BackupBinaryDir);
}
@@ -665,7 +674,7 @@ int cmCTestScriptHandler::PerformExtraUpdates()
"Run Update: " << fullCommand << std::endl);
res = cmSystemTools::RunSingleCommand(
fullCommand.c_str(), &output, &output, &retVal, cvsArgs[0].c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
if (!res || retVal != 0) {
cmSystemTools::Error("Unable to perform extra updates:\n", eu.c_str(),
"\nWith output:\n", output.c_str());
@@ -707,9 +716,9 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
}
// make sure the binary directory exists if it isn't the srcdir
- if (!cmSystemTools::FileExists(this->BinaryDir.c_str()) &&
+ if (!cmSystemTools::FileExists(this->BinaryDir) &&
this->SourceDir != this->BinaryDir) {
- if (!cmSystemTools::MakeDirectory(this->BinaryDir.c_str())) {
+ if (!cmSystemTools::MakeDirectory(this->BinaryDir)) {
cmSystemTools::Error("Unable to create the binary directory:\n",
this->BinaryDir.c_str());
this->RestoreBackupDirectories();
@@ -769,11 +778,11 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
"Run cmake command: " << command << std::endl);
res = cmSystemTools::RunSingleCommand(
command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
if (!this->CMOutFile.empty()) {
std::string cmakeOutputFile = this->CMOutFile;
- if (!cmSystemTools::FileIsFullPath(cmakeOutputFile.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(cmakeOutputFile)) {
cmakeOutputFile = this->BinaryDir + "/" + cmakeOutputFile;
}
@@ -808,7 +817,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
"Run ctest command: " << command << std::endl);
res = cmSystemTools::RunSingleCommand(
command.c_str(), &output, &output, &retVal, this->BinaryDir.c_str(),
- this->HandlerVerbose, 0 /*this->TimeOut*/);
+ this->HandlerVerbose, cmDuration::zero() /*this->TimeOut*/);
// did something critical fail in ctest
if (!res || cmakeFailed || retVal & cmCTest::BUILD_ERRORS) {
@@ -830,7 +839,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
}
}
- // if all was succesful, delete the backup dirs to free up disk space
+ // if all was successful, delete the backup dirs to free up disk space
if (this->Backup) {
cmSystemTools::RemoveADirectory(this->BackupSourceDir);
cmSystemTools::RemoveADirectory(this->BackupBinaryDir);
@@ -867,10 +876,10 @@ void cmCTestScriptHandler::RestoreBackupDirectories()
// the backed up dirs
if (this->Backup) {
// if for some reason those directories exist then first delete them
- if (cmSystemTools::FileExists(this->SourceDir.c_str())) {
+ if (cmSystemTools::FileExists(this->SourceDir)) {
cmSystemTools::RemoveADirectory(this->SourceDir);
}
- if (cmSystemTools::FileExists(this->BinaryDir.c_str())) {
+ if (cmSystemTools::FileExists(this->BinaryDir)) {
cmSystemTools::RemoveADirectory(this->BinaryDir);
}
// rename the src and binary directories
@@ -909,7 +918,7 @@ bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
std::string check = sname;
check += "/CMakeCache.txt";
- if (!cmSystemTools::FileExists(check.c_str())) {
+ if (!cmSystemTools::FileExists(check)) {
return false;
}
@@ -955,19 +964,26 @@ bool cmCTestScriptHandler::TryToRemoveBinaryDirectoryOnce(
return cmSystemTools::RemoveADirectory(directoryPath);
}
-double cmCTestScriptHandler::GetRemainingTimeAllowed()
+cmDuration cmCTestScriptHandler::GetRemainingTimeAllowed()
{
if (!this->Makefile) {
- return 1.0e7;
+ return cmCTest::MaxDuration();
}
const char* timelimitS = this->Makefile->GetDefinition("CTEST_TIME_LIMIT");
if (!timelimitS) {
- return 1.0e7;
+ return cmCTest::MaxDuration();
}
- double timelimit = atof(timelimitS);
+ auto timelimit = cmDuration(atof(timelimitS));
- return timelimit - cmSystemTools::GetTime() + this->ScriptStartTime;
+ auto duration = std::chrono::duration_cast<cmDuration>(
+ std::chrono::steady_clock::now() - this->ScriptStartTime);
+ return (timelimit - duration);
+}
+
+void cmCTestScriptHandler::SetRunCurrentScript(bool value)
+{
+ this->ShouldRunCurrentScript = value;
}
diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h
index b6cd97b73..cf0762ec2 100644
--- a/Source/CTest/cmCTestScriptHandler.h
+++ b/Source/CTest/cmCTestScriptHandler.h
@@ -6,7 +6,9 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
+#include <chrono>
#include <string>
#include <vector>
@@ -93,9 +95,9 @@ public:
/**
* Return the time remaianing that the script is allowed to run in
* seconds if the user has set the variable CTEST_TIME_LIMIT. If that has
- * not been set it returns 1e7 seconds
+ * not been set it returns a very large value.
*/
- double GetRemainingTimeAllowed();
+ cmDuration GetRemainingTimeAllowed();
cmCTestScriptHandler();
~cmCTestScriptHandler() override;
@@ -104,6 +106,9 @@ public:
void CreateCMake();
cmake* GetCMake() { return this->CMake; }
+
+ void SetRunCurrentScript(bool value);
+
private:
// reads in a script
int ReadInScript(const std::string& total_script_arg);
@@ -134,6 +139,8 @@ private:
std::vector<std::string> ConfigurationScripts;
std::vector<bool> ScriptProcessScope;
+ bool ShouldRunCurrentScript;
+
bool Backup;
bool EmptyBinDir;
bool EmptyBinDirOnce;
@@ -156,7 +163,7 @@ private:
double ContinuousDuration;
// what time in seconds did this script start running
- double ScriptStartTime;
+ std::chrono::steady_clock::time_point ScriptStartTime;
cmMakefile* Makefile;
cmGlobalGenerator* GlobalGenerator;
diff --git a/Source/CTest/cmCTestStartCommand.cxx b/Source/CTest/cmCTestStartCommand.cxx
index 4f0d87b1b..38ee62308 100644
--- a/Source/CTest/cmCTestStartCommand.cxx
+++ b/Source/CTest/cmCTestStartCommand.cxx
@@ -126,7 +126,7 @@ bool cmCTestStartCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- this->Makefile->AddDefinition("CTEST_RUN_CURRENT_SCRIPT", "OFF");
+ this->CTest->SetRunCurrentScript(false);
this->CTest->SetSuppressUpdatingCTestConfiguration(true);
int model = this->CTest->GetTestModelFromString(smodel);
this->CTest->SetTestModel(model);
diff --git a/Source/CTest/cmCTestSubmitCommand.cxx b/Source/CTest/cmCTestSubmitCommand.cxx
index 1794ca64b..34adb4af3 100644
--- a/Source/CTest/cmCTestSubmitCommand.cxx
+++ b/Source/CTest/cmCTestSubmitCommand.cxx
@@ -229,7 +229,7 @@ bool cmCTestSubmitCommand::CheckArgumentValue(std::string const& arg)
}
if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg.c_str())) {
+ if (cmSystemTools::FileExists(arg)) {
this->Files.insert(arg);
} else {
std::ostringstream e;
diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx
index e51e16843..08d05c8e8 100644
--- a/Source/CTest/cmCTestSubmitHandler.cxx
+++ b/Source/CTest/cmCTestSubmitHandler.cxx
@@ -6,6 +6,7 @@
#include "cm_jsoncpp_reader.h"
#include "cm_jsoncpp_value.h"
#include "cmsys/Process.h"
+#include <chrono>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
@@ -15,6 +16,7 @@
#include "cmCTestScriptHandler.h"
#include "cmCryptoHash.h"
#include "cmCurl.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmProcessOutput.h"
#include "cmState.h"
@@ -192,13 +194,13 @@ bool cmCTestSubmitHandler::SubmitUsingFTP(const std::string& localprefix,
::curl_easy_setopt(curl, CURLOPT_UPLOAD, 1);
std::string local_file = file;
- if (!cmSystemTools::FileExists(local_file.c_str())) {
+ if (!cmSystemTools::FileExists(local_file)) {
local_file = localprefix + "/" + file;
}
std::string upload_as =
url + "/" + remoteprefix + cmSystemTools::GetFilenameName(file);
- if (!cmSystemTools::FileExists(local_file.c_str())) {
+ if (!cmSystemTools::FileExists(local_file)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Cannot find file: " << local_file << std::endl);
::curl_easy_cleanup(curl);
@@ -385,7 +387,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
::curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
std::string local_file = file;
- if (!cmSystemTools::FileExists(local_file.c_str())) {
+ if (!cmSystemTools::FileExists(local_file)) {
local_file = localprefix + "/" + file;
}
std::string remote_file =
@@ -427,7 +429,7 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
cmSystemTools::ComputeFileHash(local_file, cmCryptoHash::AlgoMD5);
}
- if (!cmSystemTools::FileExists(local_file.c_str())) {
+ if (!cmSystemTools::FileExists(local_file)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
" Cannot find file: " << local_file << std::endl);
::curl_easy_cleanup(curl);
@@ -496,10 +498,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
? ""
: this->GetOption("RetryCount");
- int delay = retryDelay.empty()
- ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
- .c_str())
- : atoi(retryDelay.c_str());
+ auto delay = cmDuration(
+ retryDelay.empty()
+ ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay")
+ .c_str())
+ : atoi(retryDelay.c_str()));
int count = retryCount.empty()
? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryCount")
.c_str())
@@ -507,12 +510,12 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix,
for (int i = 0; i < count; i++) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Submit failed, waiting " << delay
+ " Submit failed, waiting " << delay.count()
<< " seconds...\n",
this->Quiet);
- double stop = cmSystemTools::GetTime() + delay;
- while (cmSystemTools::GetTime() < stop) {
+ auto stop = std::chrono::steady_clock::now() + delay;
+ while (std::chrono::steady_clock::now() < stop) {
cmSystemTools::Delay(100);
}
@@ -769,7 +772,7 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command,
std::string lfname = localprefix;
cmSystemTools::ConvertToUnixSlashes(lfname);
lfname += "/" + file;
- lfname = cmSystemTools::ConvertToOutputPath(lfname.c_str());
+ lfname = cmSystemTools::ConvertToOutputPath(lfname);
argv[1] = lfname.c_str();
std::string rfname = url + "/" + remoteprefix + file;
argv[2] = rfname.c_str();
@@ -895,7 +898,7 @@ bool cmCTestSubmitHandler::SubmitUsingXMLRPC(
xmlrpc_value* result;
std::string local_file = file;
- if (!cmSystemTools::FileExists(local_file.c_str())) {
+ if (!cmSystemTools::FileExists(local_file)) {
local_file = localprefix + "/" + file;
}
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
@@ -1031,11 +1034,15 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
std::string retryCountString = this->GetOption("RetryCount") == nullptr
? ""
: this->GetOption("RetryCount");
- unsigned long retryDelay = 0;
+ auto retryDelay = std::chrono::seconds(0);
if (!retryDelayString.empty()) {
- if (!cmSystemTools::StringToULong(retryDelayString.c_str(), &retryDelay)) {
+ unsigned long retryDelayValue = 0;
+ if (!cmSystemTools::StringToULong(retryDelayString.c_str(),
+ &retryDelayValue)) {
cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : "
<< retryDelayString << std::endl);
+ } else {
+ retryDelay = std::chrono::seconds(retryDelayValue);
}
}
unsigned long retryCount = 0;
@@ -1063,6 +1070,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()) << "&"
@@ -1071,8 +1080,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();
@@ -1087,12 +1096,12 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
// If request failed, wait and retry.
for (unsigned long i = 0; i < retryCount; i++) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Request failed, waiting " << retryDelay
+ " Request failed, waiting " << retryDelay.count()
<< " seconds...\n",
this->Quiet);
- double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
- while (cmSystemTools::GetTime() < stop) {
+ auto stop = std::chrono::steady_clock::now() + retryDelay;
+ while (std::chrono::steady_clock::now() < stop) {
cmSystemTools::Delay(100);
}
@@ -1161,12 +1170,12 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file,
// If upload failed, wait and retry.
for (unsigned long i = 0; i < retryCount; i++) {
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
- " Upload failed, waiting " << retryDelay
+ " Upload failed, waiting " << retryDelay.count()
<< " seconds...\n",
this->Quiet);
- double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay);
- while (cmSystemTools::GetTime() < stop) {
+ auto stop = std::chrono::steady_clock::now() + retryDelay;
+ while (std::chrono::steady_clock::now() < stop) {
cmSystemTools::Delay(100);
}
@@ -1521,7 +1530,7 @@ int cmCTestSubmitHandler::ProcessHandler()
this->CTest->GetCTestConfiguration("DropLocation");
// change to the build directory so that we can uses a relative path
- // on windows since scp dosn't support "c:" a drive in the path
+ // on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
if (!this->SubmitUsingSCP(this->CTest->GetCTestConfiguration("ScpCommand"),
@@ -1540,7 +1549,7 @@ int cmCTestSubmitHandler::ProcessHandler()
std::string location = this->CTest->GetCTestConfiguration("DropLocation");
// change to the build directory so that we can uses a relative path
- // on windows since scp dosn't support "c:" a drive in the path
+ // on windows since scp doesn't support "c:" a drive in the path
cmWorkingDirectory workdir(buildDirectory);
cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
" Change directory: " << buildDirectory << std::endl,
diff --git a/Source/CTest/cmCTestTestCommand.cxx b/Source/CTest/cmCTestTestCommand.cxx
index febd39e76..daedf6255 100644
--- a/Source/CTest/cmCTestTestCommand.cxx
+++ b/Source/CTest/cmCTestTestCommand.cxx
@@ -4,9 +4,11 @@
#include "cmCTest.h"
#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
+#include <chrono>
#include <sstream>
#include <stdlib.h>
#include <vector>
@@ -36,14 +38,14 @@ cmCTestGenericHandler* cmCTestTestCommand::InitializeHandler()
const char* ctestTimeout =
this->Makefile->GetDefinition("CTEST_TEST_TIMEOUT");
- double timeout;
+ cmDuration timeout;
if (ctestTimeout) {
- timeout = atof(ctestTimeout);
+ timeout = cmDuration(atof(ctestTimeout));
} else {
timeout = this->CTest->GetTimeOut();
- if (timeout <= 0) {
+ if (timeout <= cmDuration::zero()) {
// By default use timeout of 10 minutes
- timeout = 600;
+ timeout = std::chrono::minutes(10);
}
}
this->CTest->SetTimeOut(timeout);
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index c7ed92725..84d8926ea 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmCTestTestHandler.h"
#include <algorithm>
+#include <chrono>
#include <cmsys/Base64.h>
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
@@ -18,9 +19,9 @@
#include "cmAlgorithms.h"
#include "cmCTest.h"
-#include "cmCTestBatchTestHandler.h"
#include "cmCTestMultiProcessHandler.h"
#include "cmCommand.h"
+#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
@@ -69,7 +70,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
for (std::string const& arg : args) {
std::string fname;
- if (cmSystemTools::FileIsFullPath(arg.c_str())) {
+ if (cmSystemTools::FileIsFullPath(arg)) {
fname = arg;
} else {
fname = cwd;
@@ -144,7 +145,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
fname += "/";
fname += args[0];
- if (!cmSystemTools::FileExists(fname.c_str())) {
+ if (!cmSystemTools::FileExists(fname)) {
// No subdirectory? So what...
return true;
}
@@ -346,7 +347,7 @@ void cmCTestTestHandler::Initialize()
{
this->Superclass::Initialize();
- this->ElapsedTestingTime = -1;
+ this->ElapsedTestingTime = cmDuration();
this->TestResults.clear();
@@ -484,12 +485,11 @@ int cmCTestTestHandler::ProcessHandler()
int total;
// start the real time clock
- double clock_start, clock_finish;
- clock_start = cmSystemTools::GetTime();
+ auto clock_start = std::chrono::steady_clock::now();
this->ProcessDirectory(passed, failed);
- clock_finish = cmSystemTools::GetTime();
+ auto clock_finish = std::chrono::steady_clock::now();
total = int(passed.size()) + int(failed.size());
@@ -540,7 +540,8 @@ int cmCTestTestHandler::ProcessHandler()
this->PrintLabelOrSubprojectSummary(false);
}
char realBuf[1024];
- sprintf(realBuf, "%6.2f sec", clock_finish - clock_start);
+ cmDuration durationInSecs = clock_finish - clock_start;
+ sprintf(realBuf, "%6.2f sec", durationInSecs.count());
cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT,
"\nTotal Test time (real) = " << realBuf << "\n",
this->Quiet);
@@ -650,7 +651,8 @@ void cmCTestTestHandler::PrintLabelOrSubprojectSummary(bool doSubProject)
for (std::string const& l : p.Labels) {
// only use labels found in labels
if (labels.find(l) != labels.end()) {
- labelTimes[l] += result.ExecutionTime * result.Properties->Processors;
+ labelTimes[l] +=
+ result.ExecutionTime.count() * result.Properties->Processors;
++labelCounts[l];
}
}
@@ -1200,12 +1202,10 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
{
this->ComputeTestList();
this->StartTest = this->CTest->CurrentTime();
- this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
- double elapsed_time_start = cmSystemTools::GetTime();
+ this->StartTestTime = std::chrono::system_clock::now();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
- cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs()
- ? new cmCTestBatchTestHandler
- : new cmCTestMultiProcessHandler;
+ cmCTestMultiProcessHandler* parallel = new cmCTestMultiProcessHandler;
parallel->SetCTest(this->CTest);
parallel->SetParallelLevel(this->CTest->GetParallelLevel());
parallel->SetTestHandler(this);
@@ -1236,7 +1236,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
p.Cost = static_cast<float>(rand());
}
- if (p.Timeout == 0 && this->CTest->GetGlobalTimeout() != 0) {
+ if (p.Timeout == cmDuration::zero() &&
+ this->CTest->GetGlobalTimeout() != cmDuration::zero()) {
p.Timeout = this->CTest->GetGlobalTimeout();
}
@@ -1267,8 +1268,9 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed,
}
delete parallel;
this->EndTest = this->CTest->CurrentTime();
- this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime());
- this->ElapsedTestingTime = cmSystemTools::GetTime() - elapsed_time_start;
+ 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;
}
@@ -1317,7 +1319,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.StartElement("NamedMeasurement");
xml.Attribute("type", "numeric/double");
xml.Attribute("name", "Execution Time");
- xml.Element("Value", result.ExecutionTime);
+ xml.Element("Value", result.ExecutionTime.count());
xml.EndElement(); // NamedMeasurement
if (!result.Reason.empty()) {
const char* reasonType = "Pass Reason";
@@ -1373,8 +1375,10 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml)
xml.Element("EndDateTime", this->EndTest);
xml.Element("EndTestTime", this->EndTestTime);
- xml.Element("ElapsedMinutes",
- static_cast<int>(this->ElapsedTestingTime / 6) / 10.0);
+ xml.Element(
+ "ElapsedMinutes",
+ std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime)
+ .count());
xml.EndElement(); // Testing
this->CTest->EndXML(xml);
}
@@ -1572,7 +1576,7 @@ std::string cmCTestTestHandler::FindExecutable(
// now look in the paths we specified above
for (unsigned int ai = 0; ai < attempted.size() && fullPath.empty(); ++ai) {
// first check without exe extension
- if (cmSystemTools::FileExists(attempted[ai].c_str()) &&
+ if (cmSystemTools::FileExists(attempted[ai]) &&
!cmSystemTools::FileIsDirectory(attempted[ai])) {
fullPath = cmSystemTools::CollapseFullPath(attempted[ai]);
resultingConfig = attemptedConfigs[ai];
@@ -1582,7 +1586,7 @@ std::string cmCTestTestHandler::FindExecutable(
failed.push_back(attempted[ai]);
tempPath = attempted[ai];
tempPath += cmSystemTools::GetExecutableExtension();
- if (cmSystemTools::FileExists(tempPath.c_str()) &&
+ if (cmSystemTools::FileExists(tempPath) &&
!cmSystemTools::FileIsDirectory(tempPath)) {
fullPath = cmSystemTools::CollapseFullPath(tempPath);
resultingConfig = attemptedConfigs[ai];
@@ -1818,7 +1822,7 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed()
std::string lastTestsFailedLog =
this->CTest->GetBinaryDir() + "/Testing/Temporary/" + logName;
- if (!cmSystemTools::FileExists(lastTestsFailedLog.c_str())) {
+ if (!cmSystemTools::FileExists(lastTestsFailedLog)) {
if (!this->CTest->GetShowOnly() && !this->CTest->ShouldPrintLabels()) {
cmCTestLog(this->CTest, ERROR_MESSAGE, lastTestsFailedLog
<< " does not exist!" << std::endl);
@@ -1931,7 +1935,7 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml,
} else if (measurementfile.find(cxml)) {
const std::string& filename =
cmCTest::CleanString(measurementfile.match(5));
- if (cmSystemTools::FileExists(filename.c_str())) {
+ if (cmSystemTools::FileExists(filename)) {
long len = cmSystemTools::FileLength(filename);
if (len == 0) {
std::string k1 = measurementfile.match(1);
@@ -2136,7 +2140,7 @@ bool cmCTestTestHandler::SetTestsProperties(
rt.FixturesRequired.insert(lval.begin(), lval.end());
}
if (key == "TIMEOUT") {
- rt.Timeout = atof(val.c_str());
+ rt.Timeout = cmDuration(atof(val.c_str()));
rt.ExplicitTimeout = true;
}
if (key == "COST") {
@@ -2152,9 +2156,7 @@ bool cmCTestTestHandler::SetTestsProperties(
std::vector<std::string> lval;
cmSystemTools::ExpandListArgument(val, lval);
for (std::string const& cr : lval) {
- rt.ErrorRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(cr.c_str()), std::string(cr)));
+ rt.ErrorRegularExpressions.emplace_back(cr, cr);
}
}
if (key == "PROCESSORS") {
@@ -2200,9 +2202,7 @@ bool cmCTestTestHandler::SetTestsProperties(
std::vector<std::string> lval;
cmSystemTools::ExpandListArgument(val, lval);
for (std::string const& cr : lval) {
- rt.RequiredRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(cr.c_str()), std::string(cr)));
+ rt.RequiredRegularExpressions.emplace_back(cr, cr);
}
}
if (key == "WORKING_DIRECTORY") {
@@ -2216,13 +2216,11 @@ bool cmCTestTestHandler::SetTestsProperties(
"TIMEOUT_AFTER_MATCH expects two arguments, found "
<< propArgs.size() << std::endl);
} else {
- rt.AlternateTimeout = atof(propArgs[0].c_str());
+ rt.AlternateTimeout = cmDuration(atof(propArgs[0].c_str()));
std::vector<std::string> lval;
cmSystemTools::ExpandListArgument(propArgs[1], lval);
for (std::string const& cr : lval) {
- rt.TimeoutRegularExpressions.push_back(
- std::pair<cmsys::RegularExpression, std::string>(
- cmsys::RegularExpression(cr.c_str()), std::string(cr)));
+ rt.TimeoutRegularExpressions.emplace_back(cr, cr);
}
}
}
@@ -2334,7 +2332,7 @@ bool cmCTestTestHandler::AddTest(const std::vector<std::string>& args)
test.WillFail = false;
test.Disabled = false;
test.RunSerial = false;
- test.Timeout = 0;
+ test.Timeout = cmDuration::zero();
test.ExplicitTimeout = false;
test.Cost = 0;
test.Processors = 1;
diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h
index 394d20ed0..f4978b677 100644
--- a/Source/CTest/cmCTestTestHandler.h
+++ b/Source/CTest/cmCTestTestHandler.h
@@ -6,8 +6,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCTestGenericHandler.h"
+#include "cmDuration.h"
#include "cmsys/RegularExpression.hxx"
+#include <chrono>
#include <iosfwd>
#include <map>
#include <set>
@@ -28,7 +30,6 @@ class cmCTestTestHandler : public cmCTestGenericHandler
{
friend class cmCTestRunTest;
friend class cmCTestMultiProcessHandler;
- friend class cmCTestBatchTestHandler;
public:
typedef cmCTestGenericHandler Superclass;
@@ -39,7 +40,7 @@ public:
int ProcessHandler() override;
/**
- * When both -R and -I are used should te resulting test list be the
+ * When both -R and -I are used should the resulting test list be the
* intersection or the union of the lists. By default it is the
* intersection.
*/
@@ -123,9 +124,9 @@ public:
float Cost;
int PreviousRuns;
bool RunSerial;
- double Timeout;
+ cmDuration Timeout;
bool ExplicitTimeout;
- double AlternateTimeout;
+ cmDuration AlternateTimeout;
int Index;
// Requested number of process slots
int Processors;
@@ -146,7 +147,7 @@ public:
std::string Path;
std::string Reason;
std::string FullCommandLine;
- double ExecutionTime;
+ cmDuration ExecutionTime;
int ReturnValue;
int Status;
std::string ExceptionStatus;
@@ -198,7 +199,7 @@ protected:
//! Clean test output to specified length
bool CleanTestOutput(std::string& output, size_t length);
- double ElapsedTestingTime;
+ cmDuration ElapsedTestingTime;
typedef std::vector<cmCTestTestResult> TestResultsVector;
TestResultsVector TestResults;
@@ -206,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 786ed5e47..504b2102a 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -17,6 +17,7 @@
#include "cmVersion.h"
#include "cmXMLWriter.h"
+#include <chrono>
#include <memory> // IWYU pragma: keep
#include <sstream>
@@ -175,9 +176,8 @@ int cmCTestUpdateHandler::ProcessHandler()
return -1;
}
std::string start_time = this->CTest->CurrentTime();
- unsigned int start_time_time =
- static_cast<unsigned int>(cmSystemTools::GetTime());
- double elapsed_time_start = cmSystemTools::GetTime();
+ auto start_time_time = std::chrono::system_clock::now();
+ auto elapsed_time_start = std::chrono::steady_clock::now();
bool updated = vc->Update();
std::string buildname =
@@ -224,11 +224,11 @@ 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(
- "ElapsedMinutes",
- static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start) / 6) /
- 10.0);
+ 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)
+ .count());
xml.StartElement("UpdateReturnStatus");
if (localModifications) {
@@ -257,37 +257,37 @@ int cmCTestUpdateHandler::DetectVCS(const char* dir)
"Check directory: " << sourceDirectory << std::endl,
this->Quiet);
sourceDirectory += "/.svn";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_SVN;
}
sourceDirectory = dir;
sourceDirectory += "/CVS";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_CVS;
}
sourceDirectory = dir;
sourceDirectory += "/.bzr";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_BZR;
}
sourceDirectory = dir;
sourceDirectory += "/.git";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_GIT;
}
sourceDirectory = dir;
sourceDirectory += "/.hg";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_HG;
}
sourceDirectory = dir;
sourceDirectory += "/.p4";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_P4;
}
sourceDirectory = dir;
sourceDirectory += "/.p4config";
- if (cmSystemTools::FileExists(sourceDirectory.c_str())) {
+ if (cmSystemTools::FileExists(sourceDirectory)) {
return cmCTestUpdateHandler::e_P4;
}
return cmCTestUpdateHandler::e_UNKNOWN;
diff --git a/Source/CTest/cmCTestUploadCommand.cxx b/Source/CTest/cmCTestUploadCommand.cxx
index d85f35f6f..ec78c1e87 100644
--- a/Source/CTest/cmCTestUploadCommand.cxx
+++ b/Source/CTest/cmCTestUploadCommand.cxx
@@ -51,7 +51,7 @@ bool cmCTestUploadCommand::CheckArgumentValue(std::string const& arg)
return true;
}
if (this->ArgumentDoing == ArgumentDoingFiles) {
- if (cmSystemTools::FileExists(arg.c_str())) {
+ if (cmSystemTools::FileExists(arg)) {
this->Files.insert(arg);
return true;
}
diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx
index fd7f37ac8..13fa6e1f5 100644
--- a/Source/CTest/cmCTestVC.cxx
+++ b/Source/CTest/cmCTestVC.cxx
@@ -47,7 +47,7 @@ bool cmCTestVC::InitialCheckout(const char* command)
std::string parent = cmSystemTools::GetFilenamePath(this->SourceDirectory);
cmCTestLog(this->CTest, HANDLER_OUTPUT,
" Perform checkout in directory: " << parent << "\n");
- if (!cmSystemTools::MakeDirectory(parent.c_str())) {
+ if (!cmSystemTools::MakeDirectory(parent)) {
cmCTestLog(this->CTest, ERROR_MESSAGE,
"Cannot create directory: " << parent << std::endl);
return false;
diff --git a/Source/CTest/cmParseCoberturaCoverage.cxx b/Source/CTest/cmParseCoberturaCoverage.cxx
index 61ce7d48e..5bb64247b 100644
--- a/Source/CTest/cmParseCoberturaCoverage.cxx
+++ b/Source/CTest/cmParseCoberturaCoverage.cxx
@@ -83,7 +83,7 @@ protected:
// binary directories.
for (std::string const& filePath : FilePaths) {
finalpath = filePath + "/" + filename;
- if (cmSystemTools::FileExists(finalpath.c_str())) {
+ if (cmSystemTools::FileExists(finalpath)) {
this->CurFileName = finalpath;
break;
}
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 9948eded2..f965048bb 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -93,7 +93,7 @@ bool cmParseGTMCoverage::ReadMCovFile(const char* file)
// This section accounts for lines that were previously marked
// as non-executable code (-1), if the parser comes back with
// a non-zero count, increase the count by 1 to push the line
- // into the executable code set in addtion to the count found.
+ // into the executable code set in addition to the count found.
if (coverageVector[lineoffset + linenumber] == -1 && count > 0) {
coverageVector[lineoffset + linenumber] += count + 1;
} else {
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx
index 1419743fc..18412ba35 100644
--- a/Source/CTest/cmParseMumpsCoverage.cxx
+++ b/Source/CTest/cmParseMumpsCoverage.cxx
@@ -114,7 +114,7 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
for (std::string& file : glob.GetFiles()) {
std::string name = cmSystemTools::GetFilenameName(file);
this->RoutineToDirectory[name.substr(0, name.size() - 2)] = file;
- // initialze each file, this is left out until CDash is fixed
+ // initialize each file, this is left out until CDash is fixed
// to handle large numbers of files
this->InitializeMumpsFile(file);
}
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index f3c191b8a..09ed0a914 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -2,24 +2,77 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmProcess.h"
-#include "cmProcessOutput.h"
-#include "cmSystemTools.h"
+#include "cmCTest.h"
+#include "cmCTestRunTest.h"
+#include "cmCTestTestHandler.h"
+#include "cmsys/Process.h"
+
+#include <algorithm>
+#include <fcntl.h>
#include <iostream>
+#include <signal.h>
+#include <string>
+#if !defined(_WIN32)
+#include <unistd.h>
+#endif
+
+#define CM_PROCESS_BUF_SIZE 65536
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <io.h>
+
+static int cmProcessGetPipes(int* fds)
+{
+ SECURITY_ATTRIBUTES attr;
+ HANDLE readh, writeh;
+ attr.nLength = sizeof(attr);
+ attr.lpSecurityDescriptor = nullptr;
+ attr.bInheritHandle = FALSE;
+ if (!CreatePipe(&readh, &writeh, &attr, 0))
+ return uv_translate_sys_error(GetLastError());
+ fds[0] = _open_osfhandle((intptr_t)readh, 0);
+ fds[1] = _open_osfhandle((intptr_t)writeh, 0);
+ if (fds[0] == -1 || fds[1] == -1) {
+ CloseHandle(readh);
+ CloseHandle(writeh);
+ return uv_translate_sys_error(GetLastError());
+ }
+ return 0;
+}
+#else
+#include <errno.h>
-cmProcess::cmProcess()
+static int cmProcessGetPipes(int* fds)
{
- this->Process = nullptr;
- this->Timeout = 0;
- this->TotalTime = 0;
+ if (pipe(fds) == -1) {
+ return uv_translate_sys_error(errno);
+ }
+
+ if (fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
+ close(fds[0]);
+ close(fds[1]);
+ return uv_translate_sys_error(errno);
+ }
+ return 0;
+}
+#endif
+
+cmProcess::cmProcess(cmCTestRunTest& runner)
+ : Runner(runner)
+ , Conv(cmProcessOutput::UTF8, CM_PROCESS_BUF_SIZE)
+{
+ this->Timeout = cmDuration::zero();
+ this->TotalTime = cmDuration::zero();
this->ExitValue = 0;
this->Id = 0;
- this->StartTime = 0;
+ this->StartTime = std::chrono::steady_clock::time_point();
}
cmProcess::~cmProcess()
{
- cmsysProcess_Delete(this->Process);
}
+
void cmProcess::SetCommand(const char* command)
{
this->Command = command;
@@ -30,12 +83,13 @@ void cmProcess::SetCommandArguments(std::vector<std::string> const& args)
this->Arguments = args;
}
-bool cmProcess::StartProcess()
+bool cmProcess::StartProcess(uv_loop_t& loop)
{
+ this->ProcessState = cmProcess::State::Error;
if (this->Command.empty()) {
return false;
}
- this->StartTime = cmSystemTools::GetTime();
+ this->StartTime = std::chrono::steady_clock::now();
this->ProcessArgs.clear();
// put the command as arg0
this->ProcessArgs.push_back(this->Command.c_str());
@@ -44,17 +98,83 @@ bool cmProcess::StartProcess()
this->ProcessArgs.push_back(arg.c_str());
}
this->ProcessArgs.push_back(nullptr); // null terminate the list
- this->Process = cmsysProcess_New();
- cmsysProcess_SetCommand(this->Process, &*this->ProcessArgs.begin());
- if (!this->WorkingDirectory.empty()) {
- cmsysProcess_SetWorkingDirectory(this->Process,
- this->WorkingDirectory.c_str());
+
+ cm::uv_timer_ptr timer;
+ int status = timer.init(loop, this);
+ if (status != 0) {
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE,
+ "Error initializing timer: " << uv_strerror(status)
+ << std::endl);
+ return false;
+ }
+
+ cm::uv_pipe_ptr pipe_writer;
+ cm::uv_pipe_ptr pipe_reader;
+
+ pipe_writer.init(loop, 0);
+ pipe_reader.init(loop, 0, this);
+
+ int fds[2] = { -1, -1 };
+ status = cmProcessGetPipes(fds);
+ if (status != 0) {
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE,
+ "Error initializing pipe: " << uv_strerror(status)
+ << std::endl);
+ return false;
+ }
+
+ uv_pipe_open(pipe_reader, fds[0]);
+ uv_pipe_open(pipe_writer, fds[1]);
+
+ uv_stdio_container_t stdio[3];
+ stdio[0].flags = UV_IGNORE;
+ stdio[1].flags = UV_INHERIT_STREAM;
+ stdio[1].data.stream = pipe_writer;
+ stdio[2] = stdio[1];
+
+ uv_process_options_t options = uv_process_options_t();
+ options.file = this->Command.data();
+ options.args = const_cast<char**>(this->ProcessArgs.data());
+ options.stdio_count = 3; // in, out and err
+ options.exit_cb = &cmProcess::OnExitCB;
+ options.stdio = stdio;
+
+ status =
+ uv_read_start(pipe_reader, &cmProcess::OnAllocateCB, &cmProcess::OnReadCB);
+
+ if (status != 0) {
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE,
+ "Error starting read events: " << uv_strerror(status)
+ << std::endl);
+ return false;
+ }
+
+ status = this->Process.spawn(loop, options, this);
+ if (status != 0) {
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE, "Process not started\n "
+ << this->Command << "\n[" << uv_strerror(status) << "]\n");
+ return false;
+ }
+
+ this->PipeReader = std::move(pipe_reader);
+ this->Timer = std::move(timer);
+
+ this->StartTimer();
+
+ this->ProcessState = cmProcess::State::Executing;
+ return true;
+}
+
+void cmProcess::StartTimer()
+{
+ auto properties = this->Runner.GetTestProperties();
+ auto msec =
+ std::chrono::duration_cast<std::chrono::milliseconds>(this->Timeout);
+
+ if (msec != std::chrono::milliseconds(0) || !properties->ExplicitTimeout) {
+ this->Timer.start(&cmProcess::OnTimeoutCB,
+ static_cast<uint64_t>(msec.count()), 0);
}
- cmsysProcess_SetTimeout(this->Process, this->Timeout);
- cmsysProcess_SetOption(this->Process, cmsysProcess_Option_MergeOutput, 1);
- cmsysProcess_Execute(this->Process);
- return (cmsysProcess_GetState(this->Process) ==
- cmsysProcess_State_Executing);
}
bool cmProcess::Buffer::GetLine(std::string& line)
@@ -101,145 +221,499 @@ bool cmProcess::Buffer::GetLast(std::string& line)
return false;
}
-int cmProcess::GetNextOutputLine(std::string& line, double timeout)
+void cmProcess::OnReadCB(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf)
{
- cmProcessOutput processOutput(cmProcessOutput::UTF8);
- std::string strdata;
- for (;;) {
- // Look for lines already buffered.
- if (this->Output.GetLine(line)) {
- return cmsysProcess_Pipe_STDOUT;
- }
+ auto self = static_cast<cmProcess*>(stream->data);
+ self->OnRead(nread, buf);
+}
- // Check for more data from the process.
- char* data;
- int length;
- int p = cmsysProcess_WaitForData(this->Process, &data, &length, &timeout);
- if (p == cmsysProcess_Pipe_Timeout) {
- return cmsysProcess_Pipe_Timeout;
- }
- if (p == cmsysProcess_Pipe_STDOUT) {
- processOutput.DecodeText(data, length, strdata);
- this->Output.insert(this->Output.end(), strdata.begin(), strdata.end());
- } else { // p == cmsysProcess_Pipe_None
- // The process will provide no more data.
- break;
+void cmProcess::OnRead(ssize_t nread, const uv_buf_t* buf)
+{
+ std::string line;
+ if (nread > 0) {
+ std::string strdata;
+ this->Conv.DecodeText(buf->base, static_cast<size_t>(nread), strdata);
+ this->Output.insert(this->Output.end(), strdata.begin(), strdata.end());
+
+ while (this->Output.GetLine(line)) {
+ this->Runner.CheckOutput(line);
+ line.clear();
}
+
+ return;
}
- processOutput.DecodeText(std::string(), strdata);
- if (!strdata.empty()) {
- this->Output.insert(this->Output.end(), strdata.begin(), strdata.end());
+
+ if (nread == 0) {
+ return;
+ }
+
+ // The process will provide no more data.
+ if (nread != UV_EOF) {
+ auto error = static_cast<int>(nread);
+ cmCTestLog(this->Runner.GetCTest(), ERROR_MESSAGE,
+ "Error reading stream: " << uv_strerror(error) << std::endl);
}
// Look for partial last lines.
if (this->Output.GetLast(line)) {
- return cmsysProcess_Pipe_STDOUT;
+ this->Runner.CheckOutput(line);
+ }
+
+ this->ReadHandleClosed = true;
+ this->PipeReader.reset();
+ if (this->ProcessHandleClosed) {
+ uv_timer_stop(this->Timer);
+ this->Runner.FinalizeTest();
+ }
+}
+
+void cmProcess::OnAllocateCB(uv_handle_t* handle, size_t suggested_size,
+ uv_buf_t* buf)
+{
+ auto self = static_cast<cmProcess*>(handle->data);
+ self->OnAllocate(suggested_size, buf);
+}
+
+void cmProcess::OnAllocate(size_t /*suggested_size*/, uv_buf_t* buf)
+{
+ if (this->Buf.size() != CM_PROCESS_BUF_SIZE) {
+ this->Buf.resize(CM_PROCESS_BUF_SIZE);
}
- // No more data. Wait for process exit.
- if (!cmsysProcess_WaitForExit(this->Process, &timeout)) {
- return cmsysProcess_Pipe_Timeout;
+ *buf =
+ uv_buf_init(this->Buf.data(), static_cast<unsigned int>(this->Buf.size()));
+}
+
+void cmProcess::OnTimeoutCB(uv_timer_t* timer)
+{
+ auto self = static_cast<cmProcess*>(timer->data);
+ self->OnTimeout();
+}
+
+void cmProcess::OnTimeout()
+{
+ if (this->ProcessState != cmProcess::State::Executing) {
+ return;
+ }
+ this->ProcessState = cmProcess::State::Expired;
+ bool const was_still_reading = !this->ReadHandleClosed;
+ if (!this->ReadHandleClosed) {
+ this->ReadHandleClosed = true;
+ this->PipeReader.reset();
+ }
+ if (!this->ProcessHandleClosed) {
+ // Kill the child and let our on-exit handler finish the test.
+ cmsysProcess_KillPID(static_cast<unsigned long>(this->Process->pid));
+ } else if (was_still_reading) {
+ // Our on-exit handler already ran but did not finish the test
+ // because we were still reading output. We've just dropped
+ // our read handler, so we need to finish the test now.
+ this->Runner.FinalizeTest();
+ }
+}
+
+void cmProcess::OnExitCB(uv_process_t* process, int64_t exit_status,
+ int term_signal)
+{
+ auto self = static_cast<cmProcess*>(process->data);
+ self->OnExit(exit_status, term_signal);
+}
+
+void cmProcess::OnExit(int64_t exit_status, int term_signal)
+{
+ if (this->ProcessState != cmProcess::State::Expired) {
+ if (
+#if defined(_WIN32)
+ ((DWORD)exit_status & 0xF0000000) == 0xC0000000
+#else
+ term_signal != 0
+#endif
+ ) {
+ this->ProcessState = cmProcess::State::Exception;
+ } else {
+ this->ProcessState = cmProcess::State::Exited;
+ }
}
// Record exit information.
- this->ExitValue = cmsysProcess_GetExitValue(this->Process);
- this->TotalTime = cmSystemTools::GetTime() - this->StartTime;
+ this->ExitValue = static_cast<int>(exit_status);
+ this->Signal = term_signal;
+ this->TotalTime = std::chrono::steady_clock::now() - this->StartTime;
// Because of a processor clock scew the runtime may become slightly
// negative. If someone changed the system clock while the process was
// running this may be even more. Make sure not to report a negative
// duration here.
- if (this->TotalTime <= 0.0) {
- this->TotalTime = 0.0;
- }
- // std::cerr << "Time to run: " << this->TotalTime << "\n";
- return cmsysProcess_Pipe_None;
-}
-
-// return the process status
-int cmProcess::GetProcessStatus()
-{
- if (!this->Process) {
- return cmsysProcess_State_Exited;
- }
- return cmsysProcess_GetState(this->Process);
-}
-
-int cmProcess::ReportStatus()
-{
- int result = 1;
- switch (cmsysProcess_GetState(this->Process)) {
- case cmsysProcess_State_Starting: {
- std::cerr << "cmProcess: Never started " << this->Command
- << " process.\n";
- } break;
- case cmsysProcess_State_Error: {
- std::cerr << "cmProcess: Error executing " << this->Command
- << " process: " << cmsysProcess_GetErrorString(this->Process)
- << "\n";
- } break;
- case cmsysProcess_State_Exception: {
- std::cerr << "cmProcess: " << this->Command
- << " process exited with an exception: ";
- switch (cmsysProcess_GetExitException(this->Process)) {
- case cmsysProcess_Exception_None: {
- std::cerr << "None";
- } break;
- case cmsysProcess_Exception_Fault: {
- std::cerr << "Segmentation fault";
- } break;
- case cmsysProcess_Exception_Illegal: {
- std::cerr << "Illegal instruction";
- } break;
- case cmsysProcess_Exception_Interrupt: {
- std::cerr << "Interrupted by user";
- } break;
- case cmsysProcess_Exception_Numerical: {
- std::cerr << "Numerical exception";
- } break;
- case cmsysProcess_Exception_Other: {
- std::cerr << "Unknown";
- } break;
- }
- std::cerr << "\n";
- } break;
- case cmsysProcess_State_Executing: {
- std::cerr << "cmProcess: Never terminated " << this->Command
- << " process.\n";
- } break;
- case cmsysProcess_State_Exited: {
- result = cmsysProcess_GetExitValue(this->Process);
- std::cerr << "cmProcess: " << this->Command
- << " process exited with code " << result << "\n";
- } break;
- case cmsysProcess_State_Expired: {
- std::cerr << "cmProcess: killed " << this->Command
- << " process due to timeout.\n";
- } break;
- case cmsysProcess_State_Killed: {
- std::cerr << "cmProcess: killed " << this->Command << " process.\n";
- } break;
- }
- return result;
-}
-
-void cmProcess::ChangeTimeout(double t)
+ if (this->TotalTime <= cmDuration::zero()) {
+ this->TotalTime = cmDuration::zero();
+ }
+
+ this->ProcessHandleClosed = true;
+ if (this->ReadHandleClosed) {
+ uv_timer_stop(this->Timer);
+ this->Runner.FinalizeTest();
+ }
+}
+
+cmProcess::State cmProcess::GetProcessStatus()
+{
+ return this->ProcessState;
+}
+
+void cmProcess::ChangeTimeout(cmDuration t)
{
this->Timeout = t;
- cmsysProcess_SetTimeout(this->Process, this->Timeout);
+ this->StartTimer();
}
void cmProcess::ResetStartTime()
{
- cmsysProcess_ResetStartTime(this->Process);
- this->StartTime = cmSystemTools::GetTime();
+ this->StartTime = std::chrono::steady_clock::now();
}
-int cmProcess::GetExitException()
+cmProcess::Exception cmProcess::GetExitException()
{
- return cmsysProcess_GetExitException(this->Process);
+ auto exception = Exception::None;
+#if defined(_WIN32) && !defined(__CYGWIN__)
+ auto exit_code = (DWORD) this->ExitValue;
+ if ((exit_code & 0xF0000000) != 0xC0000000) {
+ return exception;
+ }
+
+ if (exit_code) {
+ switch (exit_code) {
+ case STATUS_DATATYPE_MISALIGNMENT:
+ case STATUS_ACCESS_VIOLATION:
+ case STATUS_IN_PAGE_ERROR:
+ case STATUS_INVALID_HANDLE:
+ case STATUS_NONCONTINUABLE_EXCEPTION:
+ case STATUS_INVALID_DISPOSITION:
+ case STATUS_ARRAY_BOUNDS_EXCEEDED:
+ case STATUS_STACK_OVERFLOW:
+ exception = Exception::Fault;
+ break;
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ case STATUS_FLOAT_DIVIDE_BY_ZERO:
+ case STATUS_FLOAT_INEXACT_RESULT:
+ case STATUS_FLOAT_INVALID_OPERATION:
+ case STATUS_FLOAT_OVERFLOW:
+ case STATUS_FLOAT_STACK_CHECK:
+ case STATUS_FLOAT_UNDERFLOW:
+#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
+ case STATUS_FLOAT_MULTIPLE_FAULTS:
+#endif
+#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
+ case STATUS_FLOAT_MULTIPLE_TRAPS:
+#endif
+ case STATUS_INTEGER_DIVIDE_BY_ZERO:
+ case STATUS_INTEGER_OVERFLOW:
+ exception = Exception::Numerical;
+ break;
+ case STATUS_CONTROL_C_EXIT:
+ exception = Exception::Interrupt;
+ break;
+ case STATUS_ILLEGAL_INSTRUCTION:
+ case STATUS_PRIVILEGED_INSTRUCTION:
+ exception = Exception::Illegal;
+ break;
+ default:
+ exception = Exception::Other;
+ }
+ }
+#else
+ if (this->Signal) {
+ switch (this->Signal) {
+ case SIGSEGV:
+ exception = Exception::Fault;
+ break;
+ case SIGFPE:
+ exception = Exception::Numerical;
+ break;
+ case SIGINT:
+ exception = Exception::Interrupt;
+ break;
+ case SIGILL:
+ exception = Exception::Illegal;
+ break;
+ default:
+ exception = Exception::Other;
+ }
+ }
+#endif
+ return exception;
}
std::string cmProcess::GetExitExceptionString()
{
- return cmsysProcess_GetExceptionString(this->Process);
+ std::string exception_str;
+#if defined(_WIN32)
+ switch (this->ExitValue) {
+ case STATUS_CONTROL_C_EXIT:
+ exception_str = "User interrupt";
+ break;
+ case STATUS_FLOAT_DENORMAL_OPERAND:
+ exception_str = "Floating-point exception (denormal operand)";
+ break;
+ case STATUS_FLOAT_DIVIDE_BY_ZERO:
+ exception_str = "Divide-by-zero";
+ break;
+ case STATUS_FLOAT_INEXACT_RESULT:
+ exception_str = "Floating-point exception (inexact result)";
+ break;
+ case STATUS_FLOAT_INVALID_OPERATION:
+ exception_str = "Invalid floating-point operation";
+ break;
+ case STATUS_FLOAT_OVERFLOW:
+ exception_str = "Floating-point overflow";
+ break;
+ case STATUS_FLOAT_STACK_CHECK:
+ exception_str = "Floating-point stack check failed";
+ break;
+ case STATUS_FLOAT_UNDERFLOW:
+ exception_str = "Floating-point underflow";
+ break;
+#ifdef STATUS_FLOAT_MULTIPLE_FAULTS
+ case STATUS_FLOAT_MULTIPLE_FAULTS:
+ exception_str = "Floating-point exception (multiple faults)";
+ break;
+#endif
+#ifdef STATUS_FLOAT_MULTIPLE_TRAPS
+ case STATUS_FLOAT_MULTIPLE_TRAPS:
+ exception_str = "Floating-point exception (multiple traps)";
+ break;
+#endif
+ case STATUS_INTEGER_DIVIDE_BY_ZERO:
+ exception_str = "Integer divide-by-zero";
+ break;
+ case STATUS_INTEGER_OVERFLOW:
+ exception_str = "Integer overflow";
+ break;
+
+ case STATUS_DATATYPE_MISALIGNMENT:
+ exception_str = "Datatype misalignment";
+ break;
+ case STATUS_ACCESS_VIOLATION:
+ exception_str = "Access violation";
+ break;
+ case STATUS_IN_PAGE_ERROR:
+ exception_str = "In-page error";
+ break;
+ case STATUS_INVALID_HANDLE:
+ exception_str = "Invalid handle";
+ break;
+ case STATUS_NONCONTINUABLE_EXCEPTION:
+ exception_str = "Noncontinuable exception";
+ break;
+ case STATUS_INVALID_DISPOSITION:
+ exception_str = "Invalid disposition";
+ break;
+ case STATUS_ARRAY_BOUNDS_EXCEEDED:
+ exception_str = "Array bounds exceeded";
+ break;
+ case STATUS_STACK_OVERFLOW:
+ exception_str = "Stack overflow";
+ break;
+
+ case STATUS_ILLEGAL_INSTRUCTION:
+ exception_str = "Illegal instruction";
+ break;
+ case STATUS_PRIVILEGED_INSTRUCTION:
+ exception_str = "Privileged instruction";
+ break;
+ case STATUS_NO_MEMORY:
+ default:
+ char buf[1024];
+ _snprintf(buf, 1024, "Exit code 0x%x\n", this->ExitValue);
+ exception_str.assign(buf);
+ }
+#else
+ switch (this->Signal) {
+#ifdef SIGSEGV
+ case SIGSEGV:
+ exception_str = "Segmentation fault";
+ break;
+#endif
+#ifdef SIGBUS
+#if !defined(SIGSEGV) || SIGBUS != SIGSEGV
+ case SIGBUS:
+ exception_str = "Bus error";
+ break;
+#endif
+#endif
+#ifdef SIGFPE
+ case SIGFPE:
+ exception_str = "Floating-point exception";
+ break;
+#endif
+#ifdef SIGILL
+ case SIGILL:
+ exception_str = "Illegal instruction";
+ break;
+#endif
+#ifdef SIGINT
+ case SIGINT:
+ exception_str = "User interrupt";
+ break;
+#endif
+#ifdef SIGABRT
+ case SIGABRT:
+ exception_str = "Child aborted";
+ break;
+#endif
+#ifdef SIGKILL
+ case SIGKILL:
+ exception_str = "Child killed";
+ break;
+#endif
+#ifdef SIGTERM
+ case SIGTERM:
+ exception_str = "Child terminated";
+ break;
+#endif
+#ifdef SIGHUP
+ case SIGHUP:
+ exception_str = "SIGHUP";
+ break;
+#endif
+#ifdef SIGQUIT
+ case SIGQUIT:
+ exception_str = "SIGQUIT";
+ break;
+#endif
+#ifdef SIGTRAP
+ case SIGTRAP:
+ exception_str = "SIGTRAP";
+ break;
+#endif
+#ifdef SIGIOT
+#if !defined(SIGABRT) || SIGIOT != SIGABRT
+ case SIGIOT:
+ exception_str = "SIGIOT";
+ break;
+#endif
+#endif
+#ifdef SIGUSR1
+ case SIGUSR1:
+ exception_str = "SIGUSR1";
+ break;
+#endif
+#ifdef SIGUSR2
+ case SIGUSR2:
+ exception_str = "SIGUSR2";
+ break;
+#endif
+#ifdef SIGPIPE
+ case SIGPIPE:
+ exception_str = "SIGPIPE";
+ break;
+#endif
+#ifdef SIGALRM
+ case SIGALRM:
+ exception_str = "SIGALRM";
+ break;
+#endif
+#ifdef SIGSTKFLT
+ case SIGSTKFLT:
+ exception_str = "SIGSTKFLT";
+ break;
+#endif
+#ifdef SIGCHLD
+ case SIGCHLD:
+ exception_str = "SIGCHLD";
+ break;
+#elif defined(SIGCLD)
+ case SIGCLD:
+ exception_str = "SIGCLD";
+ break;
+#endif
+#ifdef SIGCONT
+ case SIGCONT:
+ exception_str = "SIGCONT";
+ break;
+#endif
+#ifdef SIGSTOP
+ case SIGSTOP:
+ exception_str = "SIGSTOP";
+ break;
+#endif
+#ifdef SIGTSTP
+ case SIGTSTP:
+ exception_str = "SIGTSTP";
+ break;
+#endif
+#ifdef SIGTTIN
+ case SIGTTIN:
+ exception_str = "SIGTTIN";
+ break;
+#endif
+#ifdef SIGTTOU
+ case SIGTTOU:
+ exception_str = "SIGTTOU";
+ break;
+#endif
+#ifdef SIGURG
+ case SIGURG:
+ exception_str = "SIGURG";
+ break;
+#endif
+#ifdef SIGXCPU
+ case SIGXCPU:
+ exception_str = "SIGXCPU";
+ break;
+#endif
+#ifdef SIGXFSZ
+ case SIGXFSZ:
+ exception_str = "SIGXFSZ";
+ break;
+#endif
+#ifdef SIGVTALRM
+ case SIGVTALRM:
+ exception_str = "SIGVTALRM";
+ break;
+#endif
+#ifdef SIGPROF
+ case SIGPROF:
+ exception_str = "SIGPROF";
+ break;
+#endif
+#ifdef SIGWINCH
+ case SIGWINCH:
+ exception_str = "SIGWINCH";
+ break;
+#endif
+#ifdef SIGPOLL
+ case SIGPOLL:
+ exception_str = "SIGPOLL";
+ break;
+#endif
+#ifdef SIGIO
+#if !defined(SIGPOLL) || SIGIO != SIGPOLL
+ case SIGIO:
+ exception_str = "SIGIO";
+ break;
+#endif
+#endif
+#ifdef SIGPWR
+ case SIGPWR:
+ exception_str = "SIGPWR";
+ break;
+#endif
+#ifdef SIGSYS
+ case SIGSYS:
+ exception_str = "SIGSYS";
+ break;
+#endif
+#ifdef SIGUNUSED
+#if !defined(SIGSYS) || SIGUNUSED != SIGSYS
+ case SIGUNUSED:
+ exception_str = "SIGUNUSED";
+ break;
+#endif
+#endif
+ default:
+ exception_str = "Signal ";
+ exception_str += std::to_string(this->Signal);
+ }
+#endif
+ return exception_str;
}
diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h
index dfb02fe0d..20e24b9d2 100644
--- a/Source/CTest/cmProcess.h
+++ b/Source/CTest/cmProcess.h
@@ -4,11 +4,20 @@
#define cmProcess_h
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmDuration.h"
-#include "cmsys/Process.h"
+#include "cmProcessOutput.h"
+#include "cmUVHandlePtr.h"
+#include "cm_uv.h"
+
+#include <chrono>
+#include <stddef.h>
+#include <stdint.h>
#include <string>
#include <vector>
+class cmCTestRunTest;
+
/** \class cmProcess
* \brief run a process with c++
*
@@ -17,42 +26,81 @@
class cmProcess
{
public:
- cmProcess();
+ explicit cmProcess(cmCTestRunTest& runner);
~cmProcess();
const char* GetCommand() { return this->Command.c_str(); }
void SetCommand(const char* command);
void SetCommandArguments(std::vector<std::string> const& arg);
void SetWorkingDirectory(const char* dir) { this->WorkingDirectory = dir; }
- void SetTimeout(double t) { this->Timeout = t; }
- void ChangeTimeout(double t);
+ void SetTimeout(cmDuration t) { this->Timeout = t; }
+ void ChangeTimeout(cmDuration t);
void ResetStartTime();
// Return true if the process starts
- bool StartProcess();
+ bool StartProcess(uv_loop_t& loop);
+
+ enum class State
+ {
+ Starting,
+ Error,
+ Exception,
+ Executing,
+ Exited,
+ Expired,
+ Killed,
+ Disowned
+ };
- // return the process status
- int GetProcessStatus();
- // Report the status of the program
- int ReportStatus();
+ State GetProcessStatus();
int GetId() { return this->Id; }
void SetId(int id) { this->Id = id; }
int GetExitValue() { return this->ExitValue; }
- double GetTotalTime() { return this->TotalTime; }
- int GetExitException();
+ cmDuration GetTotalTime() { return this->TotalTime; }
+
+ enum class Exception
+ {
+ None,
+ Fault,
+ Illegal,
+ Interrupt,
+ Numerical,
+ Other
+ };
+
+ Exception GetExitException();
std::string GetExitExceptionString();
- /**
- * Read one line of output but block for no more than timeout.
- * Returns:
- * cmsysProcess_Pipe_None = Process terminated and all output read
- * cmsysProcess_Pipe_STDOUT = Line came from stdout or stderr
- * cmsysProcess_Pipe_Timeout = Timeout expired while waiting
- */
- int GetNextOutputLine(std::string& line, double timeout);
private:
- double Timeout;
- double StartTime;
- double TotalTime;
- cmsysProcess* Process;
+ cmDuration Timeout;
+ std::chrono::steady_clock::time_point StartTime;
+ cmDuration TotalTime;
+ bool ReadHandleClosed = false;
+ bool ProcessHandleClosed = false;
+
+ cm::uv_process_ptr Process;
+ cm::uv_pipe_ptr PipeReader;
+ cm::uv_timer_ptr Timer;
+ std::vector<char> Buf;
+
+ cmCTestRunTest& Runner;
+ cmProcessOutput Conv;
+ int Signal = 0;
+ cmProcess::State ProcessState = cmProcess::State::Starting;
+
+ static void OnExitCB(uv_process_t* process, int64_t exit_status,
+ int term_signal);
+ static void OnTimeoutCB(uv_timer_t* timer);
+ static void OnReadCB(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf);
+ static void OnAllocateCB(uv_handle_t* handle, size_t suggested_size,
+ uv_buf_t* buf);
+
+ void OnExit(int64_t exit_status, int term_signal);
+ void OnTimeout();
+ void OnRead(ssize_t nread, const uv_buf_t* buf);
+ void OnAllocate(size_t suggested_size, uv_buf_t* buf);
+
+ void StartTimer();
+
class Buffer : public std::vector<char>
{
// Half-open index range of partial line already scanned.
diff --git a/Source/Checks/cm_cxx14_check.cmake b/Source/Checks/cm_cxx14_check.cmake
new file mode 100644
index 000000000..a78ba35af
--- /dev/null
+++ b/Source/Checks/cm_cxx14_check.cmake
@@ -0,0 +1,36 @@
+set(CMake_CXX14_BROKEN 0)
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+ if(NOT CMAKE_CXX14_STANDARD_COMPILE_OPTION)
+ set(CMake_CXX14_WORKS 0)
+ endif()
+ if(NOT DEFINED CMake_CXX14_WORKS)
+ message(STATUS "Checking if compiler supports needed C++14 constructs")
+ try_compile(CMake_CXX14_WORKS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_check.cpp
+ CMAKE_FLAGS -DCMAKE_CXX_STANDARD=14
+ OUTPUT_VARIABLE OUTPUT
+ )
+ if(CMake_CXX14_WORKS AND "${OUTPUT}" MATCHES "error: no member named.*gets.*in the global namespace")
+ set_property(CACHE CMake_CXX14_WORKS PROPERTY VALUE 0)
+ endif()
+ if(CMake_CXX14_WORKS)
+ message(STATUS "Checking if compiler supports needed C++14 constructs - yes")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if compiler supports needed C++14 constructs passed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ else()
+ message(STATUS "Checking if compiler supports needed C++14 constructs - no")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if compiler supports needed C++14 constructs failed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ endif()
+ endif()
+ if(NOT CMake_CXX14_WORKS)
+ set(CMake_CXX14_BROKEN 1)
+ endif()
+endif()
diff --git a/Source/Checks/cm_cxx14_cstdio.cpp b/Source/Checks/cm_cxx14_check.cpp
index f5806a9c6..f5806a9c6 100644
--- a/Source/Checks/cm_cxx14_cstdio.cpp
+++ b/Source/Checks/cm_cxx14_check.cpp
diff --git a/Source/Checks/cm_cxx14_cstdio.cmake b/Source/Checks/cm_cxx14_cstdio.cmake
deleted file mode 100644
index 73f7e2ed5..000000000
--- a/Source/Checks/cm_cxx14_cstdio.cmake
+++ /dev/null
@@ -1,33 +0,0 @@
-set(CMake_CXX14_CSTDIO_BROKEN 0)
-if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND CMAKE_CXX14_STANDARD_COMPILE_OPTION)
- if(NOT DEFINED CMake_CXX14_CSTDIO_WORKS)
- message(STATUS "Checking if compiler supports C++14 cstdio")
- try_compile(CMake_CXX14_CSTDIO_WORKS
- ${CMAKE_CURRENT_BINARY_DIR}
- ${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_cstdio.cpp
- CMAKE_FLAGS -DCMAKE_CXX_STANDARD=14
- OUTPUT_VARIABLE OUTPUT
- )
- if(CMake_CXX14_CSTDIO_WORKS AND "${OUTPUT}" MATCHES "error: no member named.*gets.*in the global namespace")
- set_property(CACHE CMake_CXX14_CSTDIO_WORKS PROPERTY VALUE 0)
- endif()
- if(CMake_CXX14_CSTDIO_WORKS)
- message(STATUS "Checking if compiler supports C++14 cstdio - yes")
- file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
- "Determining if compiler supports C++14 cstdio passed with the following output:\n"
- "${OUTPUT}\n"
- "\n"
- )
- else()
- message(STATUS "Checking if compiler supports C++14 cstdio - no")
- file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
- "Determining if compiler supports C++14 cstdio failed with the following output:\n"
- "${OUTPUT}\n"
- "\n"
- )
- endif()
- endif()
- if(NOT CMake_CXX14_CSTDIO_WORKS)
- set(CMake_CXX14_CSTDIO_BROKEN 1)
- endif()
-endif()
diff --git a/Source/Checks/cm_cxx17_check.cmake b/Source/Checks/cm_cxx17_check.cmake
new file mode 100644
index 000000000..83d397112
--- /dev/null
+++ b/Source/Checks/cm_cxx17_check.cmake
@@ -0,0 +1,36 @@
+set(CMake_CXX17_BROKEN 0)
+if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
+ if(NOT CMAKE_CXX17_STANDARD_COMPILE_OPTION)
+ set(CMake_CXX17_WORKS 0)
+ endif()
+ if(NOT DEFINED CMake_CXX17_WORKS)
+ message(STATUS "Checking if compiler supports needed C++17 constructs")
+ try_compile(CMake_CXX17_WORKS
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}/cm_cxx17_check.cpp
+ CMAKE_FLAGS -DCMAKE_CXX_STANDARD=17
+ OUTPUT_VARIABLE OUTPUT
+ )
+ if(CMake_CXX17_WORKS AND "${OUTPUT}" MATCHES "error: no member named.*gets.*in the global namespace")
+ set_property(CACHE CMake_CXX17_WORKS PROPERTY VALUE 0)
+ endif()
+ if(CMake_CXX17_WORKS)
+ message(STATUS "Checking if compiler supports needed C++17 constructs - yes")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
+ "Determining if compiler supports needed C++17 constructs passed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ else()
+ message(STATUS "Checking if compiler supports needed C++17 constructs - no")
+ file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
+ "Determining if compiler supports needed C++17 constructs failed with the following output:\n"
+ "${OUTPUT}\n"
+ "\n"
+ )
+ endif()
+ endif()
+ if(NOT CMake_CXX17_WORKS)
+ set(CMake_CXX17_BROKEN 1)
+ endif()
+endif()
diff --git a/Source/Checks/cm_cxx17_check.cpp b/Source/Checks/cm_cxx17_check.cpp
new file mode 100644
index 000000000..2cbf1d5e9
--- /dev/null
+++ b/Source/Checks/cm_cxx17_check.cpp
@@ -0,0 +1,7 @@
+#include <cstdio>
+#include <unordered_map>
+
+int main()
+{
+ return 0;
+}
diff --git a/Source/Checks/cm_cxx_attribute_fallthrough.cxx b/Source/Checks/cm_cxx_attribute_fallthrough.cxx
deleted file mode 100644
index 50605b70a..000000000
--- a/Source/Checks/cm_cxx_attribute_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* [])
-{
- int i = 3;
- switch (argc) {
- case 1:
- i = 0;
- __attribute__((fallthrough));
- default:
- return i;
- }
-}
diff --git a/Source/Checks/cm_cxx_fallthrough.cxx b/Source/Checks/cm_cxx_fallthrough.cxx
deleted file mode 100644
index 2825bed1e..000000000
--- a/Source/Checks/cm_cxx_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* [])
-{
- int i = 3;
- switch (argc) {
- case 1:
- i = 0;
- [[fallthrough]];
- default:
- return i;
- }
-}
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index a30a5e690..2704c4032 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -41,13 +41,6 @@ function(cm_check_cxx_feature name)
endif()
endfunction()
-cm_check_cxx_feature(fallthrough)
-if(NOT CMake_HAVE_CXX_FALLTHROUGH)
- cm_check_cxx_feature(gnu_fallthrough)
- if(NOT CMake_HAVE_CXX_GNU_FALLTHROUGH)
- cm_check_cxx_feature(attribute_fallthrough)
- endif()
-endif()
cm_check_cxx_feature(make_unique)
if(CMake_HAVE_CXX_MAKE_UNIQUE)
set(CMake_HAVE_CXX_UNIQUE_PTR 1)
diff --git a/Source/Checks/cm_cxx_gnu_fallthrough.cxx b/Source/Checks/cm_cxx_gnu_fallthrough.cxx
deleted file mode 100644
index ebc15f431..000000000
--- a/Source/Checks/cm_cxx_gnu_fallthrough.cxx
+++ /dev/null
@@ -1,11 +0,0 @@
-int main(int argc, char* [])
-{
- int i = 3;
- switch (argc) {
- case 1:
- i = 0;
- [[gnu::fallthrough]];
- default:
- return i;
- }
-}
diff --git a/Source/CursesDialog/CMakeLists.txt b/Source/CursesDialog/CMakeLists.txt
index 6023c83eb..c51b0dd0e 100644
--- a/Source/CursesDialog/CMakeLists.txt
+++ b/Source/CursesDialog/CMakeLists.txt
@@ -2,19 +2,19 @@
# file Copyright.txt or https://cmake.org/licensing for details.
set( CURSES_SRCS
- CursesDialog/cmCursesOptionsWidget
- CursesDialog/cmCursesBoolWidget
- CursesDialog/cmCursesCacheEntryComposite
- CursesDialog/cmCursesDummyWidget
- CursesDialog/cmCursesFilePathWidget
- CursesDialog/cmCursesForm
- CursesDialog/cmCursesLabelWidget
- CursesDialog/cmCursesLongMessageForm
- CursesDialog/cmCursesMainForm
- CursesDialog/cmCursesPathWidget
- CursesDialog/cmCursesStringWidget
- CursesDialog/cmCursesWidget
- CursesDialog/ccmake
+ CursesDialog/cmCursesOptionsWidget.cxx
+ CursesDialog/cmCursesBoolWidget.cxx
+ CursesDialog/cmCursesCacheEntryComposite.cxx
+ CursesDialog/cmCursesDummyWidget.cxx
+ CursesDialog/cmCursesFilePathWidget.cxx
+ CursesDialog/cmCursesForm.cxx
+ CursesDialog/cmCursesLabelWidget.cxx
+ CursesDialog/cmCursesLongMessageForm.cxx
+ CursesDialog/cmCursesMainForm.cxx
+ CursesDialog/cmCursesPathWidget.cxx
+ CursesDialog/cmCursesStringWidget.cxx
+ CursesDialog/cmCursesWidget.cxx
+ CursesDialog/ccmake.cxx
)
include_directories(${CURSES_INCLUDE_PATH})
diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx
index 97d5579c2..17cf6289a 100644
--- a/Source/CursesDialog/ccmake.cxx
+++ b/Source/CursesDialog/ccmake.cxx
@@ -75,6 +75,7 @@ int main(int argc, char const* const* argv)
argc = encoding_args.argc();
argv = encoding_args.argv();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
cmDocumentation doc;
doc.addCMakeStandardDocSections();
diff --git a/Source/LexerParser/cmCommandArgumentLexer.cxx b/Source/LexerParser/cmCommandArgumentLexer.cxx
index bf6bc2f1e..6b4fc85f2 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.cxx
+++ b/Source/LexerParser/cmCommandArgumentLexer.cxx
@@ -674,6 +674,13 @@ Modify cmCommandArgumentLexer.cxx:
/* Include the set of tokens from the parser. */
#include "cmCommandArgumentParserTokens.h"
+static const char *DCURLYVariable = "${";
+static const char *RCURLYVariable = "}";
+static const char *ATVariable = "@";
+static const char *DOLLARVariable = "$";
+static const char *LCURLYVariable = "{";
+static const char *BSLASHVariable = "\\";
+
/*--------------------------------------------------------------------------*/
#define INITIAL 0
@@ -1011,7 +1018,7 @@ YY_RULE_SETUP
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DCURLYVariable;
+ yylvalp->str = DCURLYVariable;
return cal_DCURLY;
}
YY_BREAK
@@ -1020,7 +1027,7 @@ YY_RULE_SETUP
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->RCURLYVariable;
+ yylvalp->str = RCURLYVariable;
return cal_RCURLY;
}
YY_BREAK
@@ -1029,7 +1036,7 @@ YY_RULE_SETUP
{
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->ATVariable;
+ yylvalp->str = ATVariable;
return cal_AT;
}
YY_BREAK
@@ -1064,7 +1071,7 @@ case 10:
YY_RULE_SETUP
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DOLLARVariable;
+ yylvalp->str = DOLLARVariable;
return cal_DOLLAR;
}
YY_BREAK
@@ -1072,7 +1079,7 @@ case 11:
YY_RULE_SETUP
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->LCURLYVariable;
+ yylvalp->str = LCURLYVariable;
return cal_LCURLY;
}
YY_BREAK
@@ -1080,7 +1087,7 @@ case 12:
YY_RULE_SETUP
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_BSLASH;
}
YY_BREAK
@@ -1088,7 +1095,7 @@ case 13:
YY_RULE_SETUP
{
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_SYMBOL;
}
YY_BREAK
diff --git a/Source/LexerParser/cmCommandArgumentLexer.in.l b/Source/LexerParser/cmCommandArgumentLexer.in.l
index acf18f3a7..5927b9ed3 100644
--- a/Source/LexerParser/cmCommandArgumentLexer.in.l
+++ b/Source/LexerParser/cmCommandArgumentLexer.in.l
@@ -28,6 +28,13 @@ Modify cmCommandArgumentLexer.cxx:
/* Include the set of tokens from the parser. */
#include "cmCommandArgumentParserTokens.h"
+static const char *DCURLYVariable = "${";
+static const char *RCURLYVariable = "}";
+static const char *ATVariable = "@";
+static const char *DOLLARVariable = "$";
+static const char *LCURLYVariable = "{";
+static const char *BSLASHVariable = "\\";
+
/*--------------------------------------------------------------------------*/
%}
@@ -63,21 +70,21 @@ Modify cmCommandArgumentLexer.cxx:
"${" {
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DCURLYVariable;
+ yylvalp->str = DCURLYVariable;
return cal_DCURLY;
}
"}" {
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->RCURLYVariable;
+ yylvalp->str = RCURLYVariable;
return cal_RCURLY;
}
"@" {
//std::cerr << __LINE__ << " here: [" << yytext << "]" << std::endl;
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->ATVariable;
+ yylvalp->str = ATVariable;
return cal_AT;
}
@@ -103,25 +110,25 @@ Modify cmCommandArgumentLexer.cxx:
"$" {
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->DOLLARVariable;
+ yylvalp->str = DOLLARVariable;
return cal_DOLLAR;
}
"{" {
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->LCURLYVariable;
+ yylvalp->str = LCURLYVariable;
return cal_LCURLY;
}
<ESCAPES>"\\" {
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_BSLASH;
}
<NOESCAPES>"\\" {
//yyextra->AllocateParserType(yylvalp, yytext, strlen(yytext));
- yylvalp->str = yyextra->BSLASHVariable;
+ yylvalp->str = BSLASHVariable;
return cal_SYMBOL;
}
diff --git a/Source/Modules/FindLibUUID.cmake b/Source/Modules/FindLibUUID.cmake
new file mode 100644
index 000000000..17f11c1f5
--- /dev/null
+++ b/Source/Modules/FindLibUUID.cmake
@@ -0,0 +1,85 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindLibUUID
+------------
+
+Find LibUUID include directory and library.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+An :ref:`imported target <Imported targets>` named
+``LibUUID::LibUUID`` is provided if LibUUID has been found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module defines the following variables:
+
+``LibUUID_FOUND``
+ True if LibUUID was found, false otherwise.
+``LibUUID_INCLUDE_DIRS``
+ Include directories needed to include LibUUID headers.
+``LibUUID_LIBRARIES``
+ Libraries needed to link to LibUUID.
+
+Cache Variables
+^^^^^^^^^^^^^^^
+
+This module uses the following cache variables:
+
+``LibUUID_LIBRARY``
+ The location of the LibUUID library file.
+``LibUUID_INCLUDE_DIR``
+ The location of the LibUUID include directory containing ``uuid/uuid.h``.
+
+The cache variables should not be used by project code.
+They may be set by end users to point at LibUUID components.
+#]=======================================================================]
+
+#-----------------------------------------------------------------------------
+if(CYGWIN)
+ # Note: on current version of Cygwin, linking to libuuid.dll.a doesn't
+ # import the right symbols sometimes. Fix this by linking directly
+ # to the DLL that provides the symbols, instead.
+ set(old_suffixes ${CMAKE_FIND_LIBRARY_SUFFIXES})
+ set(CMAKE_FIND_LIBRARY_SUFFIXES .dll)
+ find_library(LibUUID_LIBRARY
+ NAMES cyguuid-1.dll
+ )
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${old_suffixes})
+else()
+ find_library(LibUUID_LIBRARY
+ NAMES uuid
+ )
+endif()
+mark_as_advanced(LibUUID_LIBRARY)
+
+find_path(LibUUID_INCLUDE_DIR
+ NAMES uuid/uuid.h
+ )
+mark_as_advanced(LibUUID_INCLUDE_DIR)
+
+#-----------------------------------------------------------------------------
+include(${CMAKE_CURRENT_LIST_DIR}/../../Modules/FindPackageHandleStandardArgs.cmake)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibUUID
+ FOUND_VAR LibUUID_FOUND
+ REQUIRED_VARS LibUUID_LIBRARY LibUUID_INCLUDE_DIR
+ )
+set(LIBUUID_FOUND ${LibUUID_FOUND})
+
+#-----------------------------------------------------------------------------
+# Provide documented result variables and targets.
+if(LibUUID_FOUND)
+ set(LibUUID_INCLUDE_DIRS ${LibUUID_INCLUDE_DIR})
+ set(LibUUID_LIBRARIES ${LibUUID_LIBRARY})
+ if(NOT TARGET LibUUID::LibUUID)
+ add_library(LibUUID::LibUUID UNKNOWN IMPORTED)
+ set_target_properties(LibUUID::LibUUID PROPERTIES
+ IMPORTED_LOCATION "${LibUUID_LIBRARY}"
+ INTERFACE_INCLUDE_DIRECTORIES "${LibUUID_INCLUDE_DIRS}"
+ )
+ endif()
+endif()
diff --git a/Source/Modules/OverrideC.cmake b/Source/Modules/OverrideC.cmake
new file mode 100644
index 000000000..f8299adb0
--- /dev/null
+++ b/Source/Modules/OverrideC.cmake
@@ -0,0 +1,3 @@
+if("${CMAKE_SYSTEM_NAME};${CMAKE_C_COMPILER_ID}" STREQUAL "AIX;GNU")
+ string(APPEND CMAKE_C_FLAGS_INIT " -pthread")
+endif()
diff --git a/Source/Modules/OverrideCXX.cmake b/Source/Modules/OverrideCXX.cmake
new file mode 100644
index 000000000..13689e2c5
--- /dev/null
+++ b/Source/Modules/OverrideCXX.cmake
@@ -0,0 +1,3 @@
+if("${CMAKE_SYSTEM_NAME};${CMAKE_CXX_COMPILER_ID}" STREQUAL "AIX;GNU")
+ string(APPEND CMAKE_CXX_FLAGS_INIT " -pthread")
+endif()
diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt
index b38797bca..330b74729 100644
--- a/Source/QtDialog/CMakeLists.txt
+++ b/Source/QtDialog/CMakeLists.txt
@@ -40,7 +40,7 @@ if (Qt5Widgets_FOUND)
endif()
# We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows.
- # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly
+ # FIXME: This should be part of Qt5 CMake scripts, but unfortunately
# Qt5 support is missing there.
if(CMake_INSTALL_DEPENDENCIES AND (APPLE OR WIN32))
macro(install_qt5_plugin _qt_plugin_name _qt_plugins_var)
@@ -166,6 +166,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(cmake-gui WIN32 MACOSX_BUNDLE ${SRCS} ${MANIFEST_FILE})
target_link_libraries(cmake-gui CMakeLib ${QT_QTMAIN_LIBRARY} ${CMake_QT_LIBRARIES})
+if(WIN32)
+ target_sources(cmake-gui PRIVATE $<TARGET_OBJECTS:CMakeVersion>)
+endif()
+
# cmake-gui has not been updated for `include-what-you-use`.
# Block the tool until this is done.
set_target_properties(cmake-gui PROPERTIES
diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx
index bfd43cfde..193f4d323 100644
--- a/Source/QtDialog/CMakeSetup.cxx
+++ b/Source/QtDialog/CMakeSetup.cxx
@@ -55,6 +55,7 @@ int main(int argc, char** argv)
int argc2 = encoding_args.argc();
char const* const* argv2 = encoding_args.argv();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv2[0]);
// check docs first so that X is not need to get docs
// do docs, if args were given
diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx
index bbb2395b2..5be9ec38d 100644
--- a/Source/QtDialog/CMakeSetupDialog.cxx
+++ b/Source/QtDialog/CMakeSetupDialog.cxx
@@ -188,6 +188,9 @@ CMakeSetupDialog::CMakeSetupDialog()
connect(this->Output, SIGNAL(customContextMenuRequested(const QPoint&)),
this, SLOT(doOutputContextMenu(const QPoint&)));
+ // disable open project button
+ this->OpenProjectButton->setDisabled(true);
+
// start the cmake worker thread
this->CMakeThread = new QCMakeThread(this);
QObject::connect(this->CMakeThread, SIGNAL(cmakeInitialized()), this,
@@ -249,6 +252,10 @@ void CMakeSetupDialog::initialize()
SIGNAL(outputMessage(QString)), this,
SLOT(message(QString)));
+ QObject::connect(this->CMakeThread->cmakeInstance(),
+ SIGNAL(openPossible(bool)), this->OpenProjectButton,
+ SLOT(setEnabled(bool)));
+
QObject::connect(this->groupedCheck, SIGNAL(toggled(bool)), this,
SLOT(setGroupedView(bool)));
QObject::connect(this->advancedCheck, SIGNAL(toggled(bool)), this,
@@ -492,24 +499,10 @@ void CMakeSetupDialog::doGenerate()
this->ConfigureNeeded = true;
}
-QString CMakeSetupDialog::getProjectFilename()
-{
- QStringList nameFilter;
- nameFilter << "*.sln"
- << "*.xcodeproj";
- QDir directory(this->BinaryDirectory->currentText());
- QStringList nlnFile = directory.entryList(nameFilter);
-
- if (nlnFile.count() == 1) {
- return this->BinaryDirectory->currentText() + "/" + nlnFile.at(0);
- }
-
- return QString();
-}
-
void CMakeSetupDialog::doOpenProject()
{
- QDesktopServices::openUrl(QUrl::fromLocalFile(this->getProjectFilename()));
+ QMetaObject::invokeMethod(this->CMakeThread->cmakeInstance(), "open",
+ Qt::QueuedConnection);
}
void CMakeSetupDialog::closeEvent(QCloseEvent* e)
@@ -630,11 +623,6 @@ void CMakeSetupDialog::updateBinaryDirectory(const QString& dir)
this->BinaryDirectory->setEditText(dir);
this->BinaryDirectory->blockSignals(false);
}
- if (!this->getProjectFilename().isEmpty()) {
- this->OpenProjectButton->setEnabled(true);
- } else {
- this->OpenProjectButton->setEnabled(false);
- }
}
void CMakeSetupDialog::doBinaryBrowse()
@@ -1039,9 +1027,6 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
this->GenerateButton->setEnabled(true);
this->GenerateAction->setEnabled(true);
this->ConfigureButton->setEnabled(true);
- if (!this->getProjectFilename().isEmpty()) {
- this->OpenProjectButton->setEnabled(true);
- }
this->ConfigureButton->setText(tr("&Configure"));
this->GenerateButton->setText(tr("&Generate"));
} else if (s == ReadyGenerate) {
@@ -1049,9 +1034,6 @@ void CMakeSetupDialog::enterState(CMakeSetupDialog::State s)
this->GenerateButton->setEnabled(true);
this->GenerateAction->setEnabled(true);
this->ConfigureButton->setEnabled(true);
- if (!this->getProjectFilename().isEmpty()) {
- this->OpenProjectButton->setEnabled(true);
- }
this->ConfigureButton->setText(tr("&Configure"));
this->GenerateButton->setText(tr("&Generate"));
}
diff --git a/Source/QtDialog/CMakeSetupDialog.h b/Source/QtDialog/CMakeSetupDialog.h
index 0da28d813..7b767e598 100644
--- a/Source/QtDialog/CMakeSetupDialog.h
+++ b/Source/QtDialog/CMakeSetupDialog.h
@@ -31,7 +31,6 @@ protected slots:
void initialize();
void doConfigure();
void doGenerate();
- QString getProjectFilename();
void doOpenProject();
void doInstallForCommandLine();
void doHelp();
diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx
index d473d9b8f..a84429b8a 100644
--- a/Source/QtDialog/QCMake.cxx
+++ b/Source/QtDialog/QCMake.cxx
@@ -39,15 +39,6 @@ QCMake::QCMake(QObject* p)
std::vector<cmake::GeneratorInfo>::const_iterator it;
for (it = generators.begin(); it != generators.end(); ++it) {
- // Skip the generator "KDevelop3", since there is also
- // "KDevelop3 - Unix Makefiles", which is the full and official name.
- // The short name is actually only still there since this was the name
- // in CMake 2.4, to keep "command line argument compatibility", but
- // this is not necessary in the GUI.
- if (it->name == "KDevelop3") {
- continue;
- }
-
this->AvailableGenerators.push_back(*it);
}
}
@@ -115,6 +106,8 @@ void QCMake::setBinaryDirectory(const QString& _dir)
if (toolset) {
this->setToolset(QString::fromLocal8Bit(toolset));
}
+
+ checkOpenPossible();
}
}
@@ -183,6 +176,26 @@ void QCMake::generate()
#endif
emit this->generateDone(err);
+ checkOpenPossible();
+}
+
+void QCMake::open()
+{
+#ifdef Q_OS_WIN
+ UINT lastErrorMode = SetErrorMode(0);
+#endif
+
+ InterruptFlag = 0;
+ cmSystemTools::ResetErrorOccuredFlag();
+
+ auto successful = this->CMakeInstance->Open(
+ this->BinaryDirectory.toLocal8Bit().data(), false);
+
+#ifdef Q_OS_WIN
+ SetErrorMode(lastErrorMode);
+#endif
+
+ emit this->openDone(successful);
}
void QCMake::setProperties(const QCMakePropertyList& newProps)
@@ -450,3 +463,10 @@ void QCMake::setWarnUnusedMode(bool value)
{
this->WarnUnusedMode = value;
}
+
+void QCMake::checkOpenPossible()
+{
+ auto data = this->BinaryDirectory.toLocal8Bit().data();
+ auto possible = this->CMakeInstance->Open(data, true);
+ emit openPossible(possible);
+}
diff --git a/Source/QtDialog/QCMake.h b/Source/QtDialog/QCMake.h
index 3b8cea721..6fae7e3f5 100644
--- a/Source/QtDialog/QCMake.h
+++ b/Source/QtDialog/QCMake.h
@@ -80,6 +80,8 @@ public slots:
void configure();
/// generate the files
void generate();
+ /// open the project
+ void open();
/// set the property values
void setProperties(const QCMakePropertyList&);
/// interrupt the configure or generate process (if connecting, make a direct
@@ -111,6 +113,8 @@ public slots:
void setWarnUninitializedMode(bool value);
/// set whether to run cmake with warnings about unused variables
void setWarnUnusedMode(bool value);
+ /// check if project IDE open is possible and emit openPossible signal
+ void checkOpenPossible();
public:
/// get the list of cache properties
@@ -151,6 +155,10 @@ signals:
void debugOutputChanged(bool);
/// signal when the toolset changes
void toolsetChanged(const QString& toolset);
+ /// signal when open is done
+ void openDone(bool successful);
+ /// signal when open is done
+ void openPossible(bool possible);
protected:
cmake* CMakeInstance;
diff --git a/Source/QtDialog/RegexExplorer.cxx b/Source/QtDialog/RegexExplorer.cxx
index abed70e90..cb67f85d4 100644
--- a/Source/QtDialog/RegexExplorer.cxx
+++ b/Source/QtDialog/RegexExplorer.cxx
@@ -8,7 +8,7 @@ RegexExplorer::RegexExplorer(QWidget* p)
{
this->setupUi(this);
- for (int i = 1; i < cmsys::RegularExpression::NSUBEXP; ++i) {
+ for (int i = 1; i < cmsys::RegularExpressionMatch::NSUBEXP; ++i) {
matchNumber->addItem(QString("Match %1").arg(QString::number(i)),
QVariant(i));
}
@@ -105,7 +105,7 @@ void RegexExplorer::on_matchNumber_currentIndexChanged(int index)
QVariant itemData = matchNumber->itemData(index);
int idx = itemData.toInt();
- if (idx < 1 || idx >= cmsys::RegularExpression::NSUBEXP) {
+ if (idx < 1 || idx >= cmsys::RegularExpressionMatch::NSUBEXP) {
return;
}
diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx
index 2eb47f3e9..9ec9624ef 100644
--- a/Source/bindexplib.cxx
+++ b/Source/bindexplib.cxx
@@ -31,7 +31,7 @@
* Extension (Axel 2006-03-15)
* As soon as an object file contains an /EXPORT directive (which
* is generated by the compiler when a symbol is declared as
- * declspec(dllexport)) no to-be-exported symbols are printed,
+ * __declspec(dllexport) no to-be-exported symbols are printed,
* as the linker will see these directives, and if those directives
* are present we only export selectively (i.e. we trust the
* programmer).
@@ -50,12 +50,12 @@
*
* It created a wrong EXPORTS for the global pointers and constants.
* The Section Header has been involved to discover the missing information
-* Now the pointers are correctly supplied supplied with "DATA" descriptor
+* Now the pointers are correctly supplied with "DATA" descriptor
* the constants with no extra descriptor.
*
* Corrections (Valery Fine 16/09/96):
*
-* It didn't work for C++ code with global variables and class definitons
+* It didn't work for C++ code with global variables and class definitions
* The DumpExternalObject function has been introduced to generate .DEF file
*
* Author: Valery Fine 16/09/96 (E-mail: fine@vxcern.cern.ch)
@@ -68,8 +68,20 @@
#include <iostream>
#include <windows.h>
+#ifndef IMAGE_FILE_MACHINE_ARM
+#define IMAGE_FILE_MACHINE_ARM 0x01c0 // ARM Little-Endian
+#endif
+
+#ifndef IMAGE_FILE_MACHINE_THUMB
+#define IMAGE_FILE_MACHINE_THUMB 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
+#endif
+
#ifndef IMAGE_FILE_MACHINE_ARMNT
-#define IMAGE_FILE_MACHINE_ARMNT 0x01c4
+#define IMAGE_FILE_MACHINE_ARMNT 0x01c4 // ARM Thumb-2 Little-Endian
+#endif
+
+#ifndef IMAGE_FILE_MACHINE_ARM64
+#define IMAGE_FILE_MACHINE_ARM64 0xaa64 // ARM64 Little-Endian
#endif
typedef struct cmANON_OBJECT_HEADER_BIGOBJ
@@ -294,7 +306,6 @@ bool DumpFile(const char* filename, std::set<std::string>& symbols,
HANDLE hFile;
HANDLE hFileMapping;
LPVOID lpFileBase;
- PIMAGE_DOS_HEADER dosHeader;
hFile = CreateFileW(cmsys::Encoding::ToWide(filename).c_str(), GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING,
@@ -320,36 +331,42 @@ bool DumpFile(const char* filename, std::set<std::string>& symbols,
return false;
}
- dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
+ const PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)lpFileBase;
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
fprintf(stderr, "File is an executable. I don't dump those.\n");
return false;
- }
- /* Does it look like a COFF OBJ file??? */
- else if (((dosHeader->e_magic == IMAGE_FILE_MACHINE_I386) ||
- (dosHeader->e_magic == IMAGE_FILE_MACHINE_AMD64) ||
- (dosHeader->e_magic == IMAGE_FILE_MACHINE_ARMNT)) &&
- (dosHeader->e_sp == 0)) {
- /*
- * The two tests above aren't what they look like. They're
- * really checking for IMAGE_FILE_HEADER.Machine == i386 (0x14C)
- * and IMAGE_FILE_HEADER.SizeOfOptionalHeader == 0;
- */
- DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> symbolDumper(
- (PIMAGE_FILE_HEADER)lpFileBase, symbols, dataSymbols,
- (dosHeader->e_magic == IMAGE_FILE_MACHINE_I386));
- symbolDumper.DumpObjFile();
} else {
- // check for /bigobj format
- cmANON_OBJECT_HEADER_BIGOBJ* h = (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
- if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
- DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX> symbolDumper(
- (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols, dataSymbols,
- (h->Machine == IMAGE_FILE_MACHINE_I386));
+ const PIMAGE_FILE_HEADER imageHeader = (PIMAGE_FILE_HEADER)lpFileBase;
+ /* Does it look like a COFF OBJ file??? */
+ if (((imageHeader->Machine == IMAGE_FILE_MACHINE_I386) ||
+ (imageHeader->Machine == IMAGE_FILE_MACHINE_AMD64) ||
+ (imageHeader->Machine == IMAGE_FILE_MACHINE_ARM) ||
+ (imageHeader->Machine == IMAGE_FILE_MACHINE_ARMNT) ||
+ (imageHeader->Machine == IMAGE_FILE_MACHINE_ARM64)) &&
+ (imageHeader->Characteristics == 0)) {
+ /*
+ * The tests above are checking for IMAGE_FILE_HEADER.Machine
+ * if it contains supported machine formats (currently ARM and x86)
+ * and IMAGE_FILE_HEADER.Characteristics == 0 indicating that
+ * this is not linked COFF OBJ file;
+ */
+ DumpSymbols<IMAGE_FILE_HEADER, IMAGE_SYMBOL> symbolDumper(
+ (PIMAGE_FILE_HEADER)lpFileBase, symbols, dataSymbols,
+ (imageHeader->Machine == IMAGE_FILE_MACHINE_I386));
symbolDumper.DumpObjFile();
} else {
- printf("unrecognized file format in '%s'\n", filename);
- return false;
+ // check for /bigobj format
+ cmANON_OBJECT_HEADER_BIGOBJ* h =
+ (cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase;
+ if (h->Sig1 == 0x0 && h->Sig2 == 0xffff) {
+ DumpSymbols<cmANON_OBJECT_HEADER_BIGOBJ, cmIMAGE_SYMBOL_EX>
+ symbolDumper((cmANON_OBJECT_HEADER_BIGOBJ*)lpFileBase, symbols,
+ dataSymbols, (h->Machine == IMAGE_FILE_MACHINE_I386));
+ symbolDumper.DumpObjFile();
+ } else {
+ printf("unrecognized file format in '%s'\n", filename);
+ return false;
+ }
}
}
UnmapViewOfFile(lpFileBase);
diff --git a/Source/cmAddCompileOptionsCommand.cxx b/Source/cmAddCompileOptionsCommand.cxx
index c37fd9a39..412fb38a2 100644
--- a/Source/cmAddCompileOptionsCommand.cxx
+++ b/Source/cmAddCompileOptionsCommand.cxx
@@ -14,7 +14,7 @@ bool cmAddCompileOptionsCommand::InitialPass(
}
for (std::string const& i : args) {
- this->Makefile->AddCompileOption(i.c_str());
+ this->Makefile->AddCompileOption(i);
}
return true;
}
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 7fed52db5..1e3faefa4 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -3,6 +3,8 @@
#include "cmAddCustomCommandCommand.h"
#include <sstream>
+#include <unordered_set>
+#include <utility>
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
@@ -68,57 +70,106 @@ bool cmAddCustomCommandCommand::InitialPass(
tdoing doing = doing_nothing;
+#define MAKE_STATIC_KEYWORD(KEYWORD) \
+ static const std::string key##KEYWORD = #KEYWORD
+ MAKE_STATIC_KEYWORD(APPEND);
+ MAKE_STATIC_KEYWORD(ARGS);
+ MAKE_STATIC_KEYWORD(BYPRODUCTS);
+ MAKE_STATIC_KEYWORD(COMMAND);
+ MAKE_STATIC_KEYWORD(COMMAND_EXPAND_LISTS);
+ MAKE_STATIC_KEYWORD(COMMENT);
+ MAKE_STATIC_KEYWORD(DEPENDS);
+ MAKE_STATIC_KEYWORD(DEPFILE);
+ MAKE_STATIC_KEYWORD(IMPLICIT_DEPENDS);
+ MAKE_STATIC_KEYWORD(MAIN_DEPENDENCY);
+ MAKE_STATIC_KEYWORD(OUTPUT);
+ MAKE_STATIC_KEYWORD(OUTPUTS);
+ MAKE_STATIC_KEYWORD(POST_BUILD);
+ MAKE_STATIC_KEYWORD(PRE_BUILD);
+ MAKE_STATIC_KEYWORD(PRE_LINK);
+ MAKE_STATIC_KEYWORD(SOURCE);
+ MAKE_STATIC_KEYWORD(TARGET);
+ MAKE_STATIC_KEYWORD(USES_TERMINAL);
+ MAKE_STATIC_KEYWORD(VERBATIM);
+ MAKE_STATIC_KEYWORD(WORKING_DIRECTORY);
+#undef MAKE_STATIC_KEYWORD
+ static std::unordered_set<std::string> keywords;
+ if (keywords.empty()) {
+ keywords.insert(keyAPPEND);
+ keywords.insert(keyARGS);
+ keywords.insert(keyBYPRODUCTS);
+ keywords.insert(keyCOMMAND);
+ keywords.insert(keyCOMMAND_EXPAND_LISTS);
+ keywords.insert(keyCOMMENT);
+ keywords.insert(keyDEPENDS);
+ keywords.insert(keyDEPFILE);
+ keywords.insert(keyIMPLICIT_DEPENDS);
+ keywords.insert(keyMAIN_DEPENDENCY);
+ keywords.insert(keyOUTPUT);
+ keywords.insert(keyOUTPUTS);
+ keywords.insert(keyPOST_BUILD);
+ keywords.insert(keyPRE_BUILD);
+ keywords.insert(keyPRE_LINK);
+ keywords.insert(keySOURCE);
+ keywords.insert(keyTARGET);
+ keywords.insert(keyUSES_TERMINAL);
+ keywords.insert(keyVERBATIM);
+ keywords.insert(keyWORKING_DIRECTORY);
+ }
+
for (std::string const& copy : args) {
- if (copy == "SOURCE") {
- doing = doing_source;
- } else if (copy == "COMMAND") {
- doing = doing_command;
+ if (keywords.count(copy)) {
+ if (copy == keySOURCE) {
+ doing = doing_source;
+ } else if (copy == keyCOMMAND) {
+ doing = doing_command;
- // Save the current command before starting the next command.
- if (!currentLine.empty()) {
- commandLines.push_back(currentLine);
- currentLine.clear();
- }
- } else if (copy == "PRE_BUILD") {
- cctype = cmTarget::PRE_BUILD;
- } else if (copy == "PRE_LINK") {
- cctype = cmTarget::PRE_LINK;
- } else if (copy == "POST_BUILD") {
- cctype = cmTarget::POST_BUILD;
- } else if (copy == "VERBATIM") {
- verbatim = true;
- } else if (copy == "APPEND") {
- append = true;
- } else if (copy == "USES_TERMINAL") {
- uses_terminal = true;
- } else if (copy == "COMMAND_EXPAND_LISTS") {
- command_expand_lists = true;
- } else if (copy == "TARGET") {
- doing = doing_target;
- } else if (copy == "ARGS") {
- // Ignore this old keyword.
- } else if (copy == "DEPENDS") {
- doing = doing_depends;
- } else if (copy == "OUTPUTS") {
- doing = doing_outputs;
- } else if (copy == "OUTPUT") {
- doing = doing_output;
- } else if (copy == "BYPRODUCTS") {
- doing = doing_byproducts;
- } else if (copy == "WORKING_DIRECTORY") {
- doing = doing_working_directory;
- } else if (copy == "MAIN_DEPENDENCY") {
- doing = doing_main_dependency;
- } else if (copy == "IMPLICIT_DEPENDS") {
- doing = doing_implicit_depends_lang;
- } else if (copy == "COMMENT") {
- doing = doing_comment;
- } else if (copy == "DEPFILE") {
- doing = doing_depfile;
- if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") {
- this->SetError("Option DEPFILE not supported by " +
- this->Makefile->GetGlobalGenerator()->GetName());
- return false;
+ // Save the current command before starting the next command.
+ if (!currentLine.empty()) {
+ commandLines.push_back(currentLine);
+ currentLine.clear();
+ }
+ } else if (copy == keyPRE_BUILD) {
+ cctype = cmTarget::PRE_BUILD;
+ } else if (copy == keyPRE_LINK) {
+ cctype = cmTarget::PRE_LINK;
+ } else if (copy == keyPOST_BUILD) {
+ cctype = cmTarget::POST_BUILD;
+ } else if (copy == keyVERBATIM) {
+ verbatim = true;
+ } else if (copy == keyAPPEND) {
+ append = true;
+ } else if (copy == keyUSES_TERMINAL) {
+ uses_terminal = true;
+ } else if (copy == keyCOMMAND_EXPAND_LISTS) {
+ command_expand_lists = true;
+ } else if (copy == keyTARGET) {
+ doing = doing_target;
+ } else if (copy == keyARGS) {
+ // Ignore this old keyword.
+ } else if (copy == keyDEPENDS) {
+ doing = doing_depends;
+ } else if (copy == keyOUTPUTS) {
+ doing = doing_outputs;
+ } else if (copy == keyOUTPUT) {
+ doing = doing_output;
+ } else if (copy == keyBYPRODUCTS) {
+ doing = doing_byproducts;
+ } else if (copy == keyWORKING_DIRECTORY) {
+ doing = doing_working_directory;
+ } else if (copy == keyMAIN_DEPENDENCY) {
+ doing = doing_main_dependency;
+ } else if (copy == keyIMPLICIT_DEPENDS) {
+ doing = doing_implicit_depends_lang;
+ } else if (copy == keyCOMMENT) {
+ doing = doing_comment;
+ } else if (copy == keyDEPFILE) {
+ doing = doing_depfile;
+ if (this->Makefile->GetGlobalGenerator()->GetName() != "Ninja") {
+ this->SetError("Option DEPFILE not supported by " +
+ this->Makefile->GetGlobalGenerator()->GetName());
+ return false;
+ }
}
} else {
std::string filename;
@@ -126,7 +177,7 @@ bool cmAddCustomCommandCommand::InitialPass(
case doing_output:
case doing_outputs:
case doing_byproducts:
- if (!cmSystemTools::FileIsFullPath(copy.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(copy)) {
// This is an output to be generated, so it should be
// under the build tree. CMake 2.4 placed this under the
// source tree. However the only case that this change
@@ -153,7 +204,7 @@ bool cmAddCustomCommandCommand::InitialPass(
break;
}
- if (cmSystemTools::FileIsFullPath(filename.c_str())) {
+ if (cmSystemTools::FileIsFullPath(filename)) {
filename = cmSystemTools::CollapseFullPath(filename);
}
switch (doing) {
@@ -184,9 +235,7 @@ bool cmAddCustomCommandCommand::InitialPass(
depends.push_back(dep);
// Add the implicit dependency language and file.
- cmCustomCommand::ImplicitDependsPair entry(implicit_depends_lang,
- dep);
- implicit_depends.push_back(entry);
+ implicit_depends.emplace_back(implicit_depends_lang, dep);
// Switch back to looking for a language.
doing = doing_implicit_depends_lang;
@@ -200,7 +249,7 @@ bool cmAddCustomCommandCommand::InitialPass(
case doing_depends: {
std::string dep = copy;
cmSystemTools::ConvertToUnixSlashes(dep);
- depends.push_back(dep);
+ depends.push_back(std::move(dep));
} break;
case doing_outputs:
outputs.push_back(filename);
@@ -356,7 +405,7 @@ bool cmAddCustomCommandCommand::CheckOutputs(
for (std::string const& o : outputs) {
// Make sure the file will not be generated into the source
// directory during an out of source build.
- if (!this->Makefile->CanIWriteThisFile(o.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(o)) {
std::string e = "attempted to have a file \"" + o +
"\" in a source directory as an output of custom command.";
this->SetError(e);
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index a8d5b2edd..4655f5843 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -3,12 +3,13 @@
#include "cmAddCustomTargetCommand.h"
#include <sstream>
+#include <utility>
#include "cmCustomCommandLines.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
+#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"
@@ -116,7 +117,7 @@ bool cmAddCustomTargetCommand::InitialPass(
break;
case doing_byproducts: {
std::string filename;
- if (!cmSystemTools::FileIsFullPath(copy.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(copy)) {
filename = this->Makefile->GetCurrentBinaryDirectory();
filename += "/";
}
@@ -127,7 +128,7 @@ bool cmAddCustomTargetCommand::InitialPass(
case doing_depends: {
std::string dep = copy;
cmSystemTools::ConvertToUnixSlashes(dep);
- depends.push_back(dep);
+ depends.push_back(std::move(dep));
} break;
case doing_comment:
comment_buffer = copy;
@@ -160,35 +161,9 @@ bool cmAddCustomTargetCommand::InitialPass(
if (nameOk) {
nameOk = targetName.find(':') == std::string::npos;
}
- if (!nameOk) {
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- std::ostringstream e;
- bool issueMessage = false;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
- case cmPolicies::WARN:
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
- issueMessage = true;
- case cmPolicies::OLD:
- break;
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- issueMessage = true;
- messageType = cmake::FATAL_ERROR;
- }
- if (issueMessage) {
- /* clang-format off */
- e << "The target name \"" << targetName <<
- "\" is reserved or not valid for certain "
- "CMake features, such as generator expressions, and may result "
- "in undefined behavior.";
- /* clang-format on */
- this->Makefile->IssueMessage(messageType, e.str());
-
- if (messageType == cmake::FATAL_ERROR) {
- return false;
- }
- }
+ if (!nameOk &&
+ !this->Makefile->CheckCMP0037(targetName, cmStateEnums::UTILITY)) {
+ return false;
}
// Store the last command line finished.
@@ -235,9 +210,9 @@ bool cmAddCustomTargetCommand::InitialPass(
// Add the utility target to the makefile.
bool escapeOldStyle = !verbatim;
cmTarget* target = this->Makefile->AddUtilityCommand(
- targetName, excludeFromAll, working_directory.c_str(), byproducts, depends,
- commandLines, escapeOldStyle, comment, uses_terminal,
- command_expand_lists);
+ targetName, cmMakefile::TargetOrigin::Project, excludeFromAll,
+ working_directory.c_str(), byproducts, depends, commandLines,
+ escapeOldStyle, comment, uses_terminal, command_expand_lists);
// Add additional user-specified source files to the target.
target->AddSources(sources);
diff --git a/Source/cmAddDefinitionsCommand.cxx b/Source/cmAddDefinitionsCommand.cxx
index 261fb5baa..62e57a309 100644
--- a/Source/cmAddDefinitionsCommand.cxx
+++ b/Source/cmAddDefinitionsCommand.cxx
@@ -16,7 +16,7 @@ bool cmAddDefinitionsCommand::InitialPass(std::vector<std::string> const& args,
}
for (std::string const& i : args) {
- this->Makefile->AddDefineFlag(i.c_str());
+ this->Makefile->AddDefineFlag(i);
}
return true;
}
diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx
index 1d0376fe0..5685fdf4b 100644
--- a/Source/cmAddExecutableCommand.cxx
+++ b/Source/cmAddExecutableCommand.cxx
@@ -7,10 +7,8 @@
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmTarget.h"
-#include "cmake.h"
class cmExecutionStatus;
@@ -18,7 +16,7 @@ class cmExecutionStatus;
bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
- if (args.size() < 2) {
+ if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
}
@@ -63,35 +61,9 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
if (nameOk && !importTarget && !isAlias) {
nameOk = exename.find(':') == std::string::npos;
}
- if (!nameOk) {
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- std::ostringstream e;
- bool issueMessage = false;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
- case cmPolicies::WARN:
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
- issueMessage = true;
- case cmPolicies::OLD:
- break;
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- issueMessage = true;
- messageType = cmake::FATAL_ERROR;
- }
- if (issueMessage) {
- /* clang-format off */
- e << "The target name \"" << exename <<
- "\" is reserved or not valid for certain "
- "CMake features, such as generator expressions, and may result "
- "in undefined behavior.";
- /* clang-format on */
- this->Makefile->IssueMessage(messageType, e.str());
-
- if (messageType == cmake::FATAL_ERROR) {
- return false;
- }
- }
+ if (!nameOk &&
+ !this->Makefile->CheckCMP0037(exename, cmStateEnums::EXECUTABLE)) {
+ return false;
}
// Special modifiers are not allowed with IMPORTED signature.
@@ -127,7 +99,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- const char* aliasedName = s->c_str();
+ std::string const& aliasedName = *s;
if (this->Makefile->IsAlias(aliasedName)) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << exename << "\" because target \""
@@ -140,8 +112,7 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
if (!aliasedTarget) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" does not already "
- "exist.";
+ << aliasedName << "\" does not already exist.";
this->SetError(e.str());
return false;
}
@@ -149,15 +120,15 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
if (type != cmStateEnums::EXECUTABLE) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" is not an "
- "executable.";
+ << aliasedName << "\" is not an executable.";
this->SetError(e.str());
return false;
}
- if (aliasedTarget->IsImported()) {
+ if (aliasedTarget->IsImported() &&
+ !aliasedTarget->IsImportedGloballyVisible()) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << exename << "\" because target \""
- << aliasedName << "\" is IMPORTED.";
+ << aliasedName << "\" is imported but not globally visible.";
this->SetError(e.str());
return false;
}
@@ -191,15 +162,9 @@ bool cmAddExecutableCommand::InitialPass(std::vector<std::string> const& args,
}
}
- if (s == args.end()) {
- this->SetError(
- "called with incorrect number of arguments, no sources provided");
- return false;
- }
-
std::vector<std::string> srclists(s, args.end());
cmTarget* tgt =
- this->Makefile->AddExecutable(exename.c_str(), srclists, excludeFromAll);
+ this->Makefile->AddExecutable(exename, srclists, excludeFromAll);
if (use_win32) {
tgt->SetProperty("WIN32_EXECUTABLE", "ON");
}
diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx
index ebf17632a..1278232ac 100644
--- a/Source/cmAddLibraryCommand.cxx
+++ b/Source/cmAddLibraryCommand.cxx
@@ -7,7 +7,6 @@
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
-#include "cmPolicies.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
@@ -175,35 +174,8 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
if (nameOk && !importTarget && !isAlias) {
nameOk = libName.find(':') == std::string::npos;
}
- if (!nameOk) {
- cmake::MessageType messageType = cmake::AUTHOR_WARNING;
- std::ostringstream e;
- bool issueMessage = false;
- switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) {
- case cmPolicies::WARN:
- if (type != cmStateEnums::INTERFACE_LIBRARY) {
- e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
- issueMessage = true;
- }
- case cmPolicies::OLD:
- break;
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- issueMessage = true;
- messageType = cmake::FATAL_ERROR;
- }
- if (issueMessage) {
- e << "The target name \"" << libName
- << "\" is reserved or not valid for certain "
- "CMake features, such as generator expressions, and may result "
- "in undefined behavior.";
- this->Makefile->IssueMessage(messageType, e.str());
-
- if (messageType == cmake::FATAL_ERROR) {
- return false;
- }
- }
+ if (!nameOk && !this->Makefile->CheckCMP0037(libName, type)) {
+ return false;
}
if (isAlias) {
@@ -226,7 +198,7 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- const char* aliasedName = s->c_str();
+ std::string const& aliasedName = *s;
if (this->Makefile->IsAlias(aliasedName)) {
std::ostringstream e;
e << "cannot create ALIAS target \"" << libName << "\" because target \""
@@ -256,13 +228,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
this->SetError(e.str());
return false;
}
- if (aliasedTarget->IsImported()) {
- std::ostringstream e;
- e << "cannot create ALIAS target \"" << libName << "\" because target \""
- << aliasedName << "\" is IMPORTED.";
- this->SetError(e.str());
- return false;
- }
this->Makefile->AddAlias(libName, aliasedName);
return true;
}
@@ -362,14 +327,6 @@ bool cmAddLibraryCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
- if (s == args.end()) {
- std::string msg = "You have called ADD_LIBRARY for library ";
- msg += args[0];
- msg += " without any source files. This typically indicates a problem ";
- msg += "with your CMakeLists.txt file";
- cmSystemTools::Message(msg.c_str(), "Warning");
- }
-
srclists.insert(srclists.end(), s, args.end());
this->Makefile->AddLibrary(libName, type, srclists, excludeFromAll);
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 1727ca56f..f673c7265 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -44,7 +44,7 @@ bool cmAddSubDirectoryCommand::InitialPass(
// Compute the full path to the specified source directory.
// Interpret a relative path with respect to the current source directory.
std::string srcPath;
- if (cmSystemTools::FileIsFullPath(srcArg.c_str())) {
+ if (cmSystemTools::FileIsFullPath(srcArg)) {
srcPath = srcArg;
} else {
srcPath = this->Makefile->GetCurrentSourceDirectory();
@@ -94,7 +94,7 @@ bool cmAddSubDirectoryCommand::InitialPass(
} else {
// Use the binary directory specified.
// Interpret a relative path with respect to the current binary directory.
- if (cmSystemTools::FileIsFullPath(binArg.c_str())) {
+ if (cmSystemTools::FileIsFullPath(binArg)) {
binPath = binArg;
} else {
binPath = this->Makefile->GetCurrentBinaryDirectory();
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index 69d0ed6a4..3380b78ca 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -43,22 +43,6 @@ inline bool cmHasLiteralSuffixImpl(const char* str1, const char* str2,
}
template <typename T, size_t N>
-const T* cmArrayBegin(const T (&a)[N])
-{
- return a;
-}
-template <typename T, size_t N>
-const T* cmArrayEnd(const T (&a)[N])
-{
- return a + N;
-}
-template <typename T, size_t N>
-size_t cmArraySize(const T (&)[N])
-{
- return N;
-}
-
-template <typename T, size_t N>
bool cmHasLiteralPrefix(const T& str1, const char (&str2)[N])
{
return cmHasLiteralPrefixImpl(str1, str2, N - 1);
@@ -418,6 +402,67 @@ std::unique_ptr<T> make_unique(Args&&... args)
#endif
+#if __cplusplus >= 201703L || defined(_MSVC_LANG) && _MSVC_LANG >= 201703L
+
+using std::size;
+
+#else
+
+// std::size backport from C++17.
+template <class C>
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+constexpr
+#endif
+ auto
+ size(C const& c) -> decltype(c.size())
+{
+ return c.size();
+}
+
+template <typename T, size_t N>
+#if !defined(_MSC_VER) || _MSC_VER >= 1900
+constexpr
+#endif
+ std::size_t
+ size(const T (&)[N]) throw()
+{
+ return N;
+}
+
+#endif
+
+#if __cplusplus >= 201402L || defined(_MSVC_LANG) && _MSVC_LANG >= 201402L
+
+using std::cbegin;
+using std::cend;
+
+#else
+
+// std::c{begin,end} backport from C++14
+template <class C>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+auto cbegin(C const& c)
+#else
+constexpr auto cbegin(C const& c) noexcept(noexcept(std::begin(c)))
+#endif
+ -> decltype(std::begin(c))
+{
+ return std::begin(c);
+}
+
+template <class C>
+#if defined(_MSC_VER) && _MSC_VER < 1900
+auto cend(C const& c)
+#else
+constexpr auto cend(C const& c) noexcept(noexcept(std::end(c)))
+#endif
+ -> decltype(std::end(c))
+{
+ return std::end(c);
+}
+
+#endif
+
} // namespace cm
#endif
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 847a41660..1f9f5802a 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -26,7 +26,7 @@ bool cmAuxSourceDirectoryCommand::InitialPass(
std::string sourceListValue;
std::string const& templateDirectory = args[0];
std::string tdir;
- if (!cmSystemTools::FileIsFullPath(templateDirectory.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(templateDirectory)) {
tdir = this->Makefile->GetCurrentSourceDirectory();
tdir += "/";
tdir += templateDirectory;
@@ -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;
@@ -65,7 +63,7 @@ bool cmAuxSourceDirectoryCommand::InitialPass(
// depends can be done
cmSourceFile* sf = this->Makefile->GetOrCreateSource(fullname);
sf->SetProperty("ABSTRACT", "0");
- files.push_back(fullname);
+ files.push_back(std::move(fullname));
}
}
}
diff --git a/Source/cmCMakeHostSystemInformationCommand.cxx b/Source/cmCMakeHostSystemInformationCommand.cxx
index 5106f522d..662dd7421 100644
--- a/Source/cmCMakeHostSystemInformationCommand.cxx
+++ b/Source/cmCMakeHostSystemInformationCommand.cxx
@@ -8,6 +8,9 @@
#include "cmsys/SystemInformation.hxx"
#if defined(_WIN32)
+#include "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmGlobalVisualStudio15Generator.h"
#include "cmSystemTools.h"
#include "cmVSSetupHelper.h"
#define HAVE_VS_SETUP_HELPER
@@ -127,6 +130,17 @@ bool cmCMakeHostSystemInformationCommand::GetValue(
value = this->ValueToString(info.GetOSPlatform());
#ifdef HAVE_VS_SETUP_HELPER
} else if (key == "VS_15_DIR") {
+ // If generating for the VS 15 IDE, use the same instance.
+ cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator();
+ if (cmHasLiteralPrefix(gg->GetName(), "Visual Studio 15 ")) {
+ cmGlobalVisualStudio15Generator* vs15gen =
+ static_cast<cmGlobalVisualStudio15Generator*>(gg);
+ if (vs15gen->GetVSInstance(value)) {
+ return true;
+ }
+ }
+
+ // Otherwise, find a VS 15 instance ourselves.
cmVSSetupAPIHelper vsSetupAPIHelper;
if (vsSetupAPIHelper.GetVSInstanceInfo(value)) {
cmSystemTools::ConvertToUnixSlashes(value);
diff --git a/Source/cmCMakeHostSystemInformationCommand.h b/Source/cmCMakeHostSystemInformationCommand.h
index bfff8f1a1..b8716418c 100644
--- a/Source/cmCMakeHostSystemInformationCommand.h
+++ b/Source/cmCMakeHostSystemInformationCommand.h
@@ -20,7 +20,7 @@ class SystemInformation;
* \brief Query host system specific information
*
* cmCMakeHostSystemInformationCommand queries system information of
- * the sytem on which CMake runs.
+ * the system on which CMake runs.
*/
class cmCMakeHostSystemInformationCommand : public cmCommand
{
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index e1e11afad..1ec76acf2 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -108,12 +108,12 @@ const char* CCONV cmGetProjectName(void* arg)
const char* CCONV cmGetHomeDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetHomeDirectory();
+ return mf->GetHomeDirectory().c_str();
}
const char* CCONV cmGetHomeOutputDirectory(void* arg)
{
cmMakefile* mf = static_cast<cmMakefile*>(arg);
- return mf->GetHomeOutputDirectory();
+ return mf->GetHomeOutputDirectory().c_str();
}
const char* CCONV cmGetStartDirectory(void* arg)
{
@@ -218,8 +218,8 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName,
}
// Pass the call to the makefile instance.
- mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr, depends2,
- commandLines);
+ mf->AddUtilityCommand(utilityName, cmMakefile::TargetOrigin::Project,
+ (all ? false : true), nullptr, depends2, commandLines);
}
void CCONV cmAddCustomCommand(void* arg, const char* source,
const char* command, int numArgs,
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 4ea14931e..3fccc386a 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -12,6 +12,7 @@
#include "cmsys/String.hxx"
#include "cmsys/SystemInformation.hxx"
#include <algorithm>
+#include <chrono>
#include <ctype.h>
#include <iostream>
#include <map>
@@ -183,7 +184,7 @@ int cmCTest::HTTPRequest(std::string url, HTTPMethod method,
::curl_easy_setopt(curl, CURLOPT_POSTFIELDS, fields.c_str());
break;
case cmCTest::HTTP_PUT:
- if (!cmSystemTools::FileExists(putFile.c_str())) {
+ if (!cmSystemTools::FileExists(putFile)) {
response = "Error: File ";
response += putFile + " does not exist.\n";
return -1;
@@ -259,7 +260,6 @@ cmCTest::cmCTest()
this->TestLoad = 0;
this->SubmitIndex = 0;
this->Failover = false;
- this->BatchJobs = false;
this->ForceNewCTestProcess = false;
this->TomorrowTag = false;
this->Verbose = false;
@@ -277,14 +277,10 @@ cmCTest::cmCTest()
this->TestModel = cmCTest::EXPERIMENTAL;
this->MaxTestNameWidth = 30;
this->InteractiveDebugMode = true;
- this->TimeOut = 0;
- this->GlobalTimeout = 0;
- this->LastStopTimeout = 24 * 60 * 60;
+ this->TimeOut = cmDuration::zero();
+ this->GlobalTimeout = cmDuration::zero();
this->CompressXMLFiles = false;
- this->CTestConfigFile.clear();
this->ScheduleType.clear();
- this->StopTime.clear();
- this->NextDayStopTime = false;
this->OutputLogFile = nullptr;
this->OutputLogFileLastTag = -1;
this->SuppressUpdatingCTestConfiguration = false;
@@ -433,7 +429,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
// Verify "Testing" directory exists:
//
std::string testingDir = this->BinaryDir + "/Testing";
- if (cmSystemTools::FileExists(testingDir.c_str())) {
+ if (cmSystemTools::FileExists(testingDir)) {
if (!cmSystemTools::FileIsDirectory(testingDir)) {
cmCTestLog(this, ERROR_MESSAGE, "File "
<< testingDir
@@ -442,7 +438,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
return 0;
}
} else {
- if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
+ if (!cmSystemTools::MakeDirectory(testingDir)) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory "
<< testingDir << std::endl);
return 0;
@@ -560,9 +556,9 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
bld_dir_fname += "/CTestConfig.cmake";
cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
- if (cmSystemTools::FileExists(bld_dir_fname.c_str())) {
+ if (cmSystemTools::FileExists(bld_dir_fname)) {
fname = bld_dir_fname;
- } else if (cmSystemTools::FileExists(src_dir_fname.c_str())) {
+ } else if (cmSystemTools::FileExists(src_dir_fname)) {
fname = src_dir_fname;
}
@@ -622,16 +618,13 @@ bool cmCTest::UpdateCTestConfiguration()
if (this->SuppressUpdatingCTestConfiguration) {
return true;
}
- std::string fileName = this->CTestConfigFile;
- if (fileName.empty()) {
- fileName = this->BinaryDir + "/CTestConfiguration.ini";
- if (!cmSystemTools::FileExists(fileName.c_str())) {
- fileName = this->BinaryDir + "/DartConfiguration.tcl";
- }
+ std::string fileName = this->BinaryDir + "/CTestConfiguration.ini";
+ if (!cmSystemTools::FileExists(fileName)) {
+ fileName = this->BinaryDir + "/DartConfiguration.tcl";
}
cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
"UpdateCTestConfiguration from :" << fileName << "\n");
- if (!cmSystemTools::FileExists(fileName.c_str())) {
+ if (!cmSystemTools::FileExists(fileName)) {
// No need to exit if we are not producing XML
if (this->ProduceXML) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot find file: " << fileName
@@ -681,7 +674,8 @@ bool cmCTest::UpdateCTestConfiguration()
this->BinaryDir = this->GetCTestConfiguration("BuildDirectory");
cmSystemTools::ChangeDirectory(this->BinaryDir);
}
- this->TimeOut = atoi(this->GetCTestConfiguration("TimeOut").c_str());
+ this->TimeOut =
+ std::chrono::seconds(atoi(this->GetCTestConfiguration("TimeOut").c_str()));
std::string const& testLoad = this->GetCTestConfiguration("TestLoad");
if (!testLoad.empty()) {
unsigned long load;
@@ -747,7 +741,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
if (!path.empty()) {
testingDir += "/" + path;
}
- if (cmSystemTools::FileExists(testingDir.c_str())) {
+ if (cmSystemTools::FileExists(testingDir)) {
if (!cmSystemTools::FileIsDirectory(testingDir)) {
cmCTestLog(this, ERROR_MESSAGE, "File "
<< testingDir << " is in the place of the testing directory"
@@ -755,7 +749,7 @@ bool cmCTest::OpenOutputFile(const std::string& path, const std::string& name,
return false;
}
} else {
- if (!cmSystemTools::MakeDirectory(testingDir.c_str())) {
+ if (!cmSystemTools::MakeDirectory(testingDir)) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot create directory " << testingDir
<< std::endl);
return false;
@@ -796,7 +790,7 @@ bool cmCTest::CTestFileExists(const std::string& filename)
{
std::string testingDir =
this->BinaryDir + "/Testing/" + this->CurrentTag + "/" + filename;
- return cmSystemTools::FileExists(testingDir.c_str());
+ return cmSystemTools::FileExists(testingDir);
}
cmCTestGenericHandler* cmCTest::GetInitializedHandler(const char* handler)
@@ -839,7 +833,8 @@ int cmCTest::ProcessSteps()
for (Part p = PartStart; notest && p != PartCount; p = Part(p + 1)) {
notest = !this->Parts[p];
}
- if (this->Parts[PartUpdate] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->Parts[PartUpdate] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
cmCTestGenericHandler* uphandler = this->GetHandler("update");
uphandler->SetPersistentOption(
"SourceDirectory",
@@ -853,33 +848,34 @@ int cmCTest::ProcessSteps()
return 0;
}
if (this->Parts[PartConfigure] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
if (this->GetHandler("configure")->ProcessHandler() < 0) {
res |= cmCTest::CONFIGURE_ERRORS;
}
}
- if (this->Parts[PartBuild] && (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ if (this->Parts[PartBuild] &&
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
if (this->GetHandler("build")->ProcessHandler() < 0) {
res |= cmCTest::BUILD_ERRORS;
}
}
if ((this->Parts[PartTest] || notest) &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
if (this->GetHandler("test")->ProcessHandler() < 0) {
res |= cmCTest::TEST_ERRORS;
}
}
if (this->Parts[PartCoverage] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
if (this->GetHandler("coverage")->ProcessHandler() < 0) {
res |= cmCTest::COVERAGE_ERRORS;
}
}
if (this->Parts[PartMemCheck] &&
- (this->GetRemainingTimeAllowed() - 120 > 0)) {
+ (this->GetRemainingTimeAllowed() > std::chrono::minutes(2))) {
this->UpdateCTestConfiguration();
if (this->GetHandler("memcheck")->ProcessHandler() < 0) {
res |= cmCTest::MEMORY_ERRORS;
@@ -894,7 +890,7 @@ int cmCTest::ProcessSteps()
for (kk = 0; kk < d.GetNumberOfFiles(); kk++) {
const char* file = d.GetFile(kk);
std::string fullname = notes_dir + "/" + file;
- if (cmSystemTools::FileExists(fullname.c_str()) &&
+ if (cmSystemTools::FileExists(fullname) &&
!cmSystemTools::FileIsDirectory(fullname)) {
if (!this->NotesFiles.empty()) {
this->NotesFiles += ";";
@@ -943,10 +939,10 @@ int cmCTest::GetTestModelFromString(const char* str)
return cmCTest::EXPERIMENTAL;
}
std::string rstr = cmSystemTools::LowerCase(str);
- if (cmHasLiteralPrefix(rstr.c_str(), "cont")) {
+ if (cmHasLiteralPrefix(rstr, "cont")) {
return cmCTest::CONTINUOUS;
}
- if (cmHasLiteralPrefix(rstr.c_str(), "nigh")) {
+ if (cmHasLiteralPrefix(rstr, "nigh")) {
return cmCTest::NIGHTLY;
}
return cmCTest::EXPERIMENTAL;
@@ -958,7 +954,7 @@ int cmCTest::GetTestModelFromString(const char* str)
//######################################################################
int cmCTest::RunMakeCommand(const char* command, std::string& output,
- int* retVal, const char* dir, int timeout,
+ int* retVal, const char* dir, cmDuration timeout,
std::ostream& ofs, Encoding encoding)
{
// First generate the command and arguments
@@ -990,7 +986,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
cmsysProcess_SetCommand(cp, &*argv.begin());
cmsysProcess_SetWorkingDirectory(cp, dir);
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
// Initialize tick's
@@ -1074,26 +1070,33 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output,
//######################################################################
int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
- int* retVal, std::ostream* log, double testTimeOut,
+ int* retVal, std::ostream* log, cmDuration testTimeOut,
std::vector<std::string>* environment, Encoding encoding)
{
bool modifyEnv = (environment && !environment->empty());
// determine how much time we have
- double timeout = this->GetRemainingTimeAllowed() - 120;
- if (this->TimeOut > 0 && this->TimeOut < timeout) {
+ cmDuration timeout = this->GetRemainingTimeAllowed();
+ if (timeout != cmCTest::MaxDuration()) {
+ timeout -= std::chrono::minutes(2);
+ }
+ if (this->TimeOut > cmDuration::zero() && this->TimeOut < timeout) {
timeout = this->TimeOut;
}
- if (testTimeOut > 0 && testTimeOut < this->GetRemainingTimeAllowed()) {
+ if (testTimeOut > cmDuration::zero() &&
+ testTimeOut < this->GetRemainingTimeAllowed()) {
timeout = testTimeOut;
}
// always have at least 1 second if we got to here
- if (timeout <= 0) {
- timeout = 1;
- }
- cmCTestLog(this, HANDLER_VERBOSE_OUTPUT,
- "Test timeout computed to be: " << timeout << "\n");
+ if (timeout <= cmDuration::zero()) {
+ timeout = std::chrono::seconds(1);
+ }
+ cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "Test timeout computed to be: "
+ << (timeout == cmCTest::MaxDuration()
+ ? std::string("infinite")
+ : std::to_string(cmDurationTo<unsigned int>(timeout)))
+ << "\n");
if (cmSystemTools::SameFile(argv[0], cmSystemTools::GetCTestCommand()) &&
!this->ForceNewCTestProcess) {
cmCTest inst;
@@ -1110,10 +1113,12 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
// make sure we pass the timeout in for any build and test
// invocations. Since --build-generator is required this is a
// good place to check for it, and to add the arguments in
- if (strcmp(i, "--build-generator") == 0 && timeout > 0) {
+ if (strcmp(i, "--build-generator") == 0 &&
+ timeout != cmCTest::MaxDuration() &&
+ timeout > cmDuration::zero()) {
args.push_back("--test-timeout");
std::ostringstream msg;
- msg << timeout;
+ msg << cmDurationTo<unsigned int>(timeout);
args.push_back(msg.str());
}
args.push_back(i);
@@ -1163,7 +1168,7 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
char* data;
@@ -1421,7 +1426,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml,
std::string note_time = this->CurrentTime();
xml.StartElement("Note");
xml.Attribute("Name", file);
- xml.Element("Time", cmSystemTools::GetTime());
+ xml.Element("Time", std::chrono::system_clock::now());
xml.Element("DateTime", note_time);
xml.StartElement("Text");
cmsys::ifstream ifs(file.c_str());
@@ -1518,7 +1523,7 @@ std::string cmCTest::Base64EncodeFile(std::string const& file)
bool cmCTest::SubmitExtraFiles(const VectorOfStrings& files)
{
for (cmsys::String const& file : files) {
- if (!cmSystemTools::FileExists(file.c_str())) {
+ if (!cmSystemTools::FileExists(file)) {
cmCTestLog(this, ERROR_MESSAGE, "Cannot find extra file: "
<< file << " to submit." << std::endl;);
return false;
@@ -1760,7 +1765,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
if (this->CheckArgument(arg, "--timeout") && i < args.size() - 1) {
i++;
- double timeout = atof(args[i].c_str());
+ auto timeout = cmDuration(atof(args[i].c_str()));
this->GlobalTimeout = timeout;
}
@@ -1798,9 +1803,6 @@ bool cmCTest::HandleCommandLineArguments(size_t& i,
if (this->CheckArgument(arg, "-V", "--verbose")) {
this->Verbose = true;
}
- if (this->CheckArgument(arg, "-B")) {
- this->BatchJobs = true;
- }
if (this->CheckArgument(arg, "-VV", "--extra-verbose")) {
this->ExtraVerbose = true;
this->Verbose = true;
@@ -2257,10 +2259,41 @@ void cmCTest::SetNotesFiles(const char* notes)
this->NotesFiles = notes;
}
-void cmCTest::SetStopTime(std::string const& time)
+void cmCTest::SetStopTime(std::string const& time_str)
{
- this->StopTime = time;
- this->DetermineNextDayStop();
+
+ struct tm* lctime;
+ time_t current_time = time(nullptr);
+ lctime = gmtime(&current_time);
+ int gm_hour = lctime->tm_hour;
+ time_t gm_time = mktime(lctime);
+ lctime = localtime(&current_time);
+ int local_hour = lctime->tm_hour;
+
+ int tzone_offset = local_hour - gm_hour;
+ if (gm_time > current_time && gm_hour < local_hour) {
+ // this means gm_time is on the next day
+ tzone_offset -= 24;
+ } else if (gm_time < current_time && gm_hour > local_hour) {
+ // this means gm_time is on the previous day
+ tzone_offset += 24;
+ }
+
+ tzone_offset *= 100;
+ char buf[1024];
+ sprintf(buf, "%d%02d%02d %s %+05i", lctime->tm_year + 1900,
+ lctime->tm_mon + 1, lctime->tm_mday, time_str.c_str(), tzone_offset);
+
+ time_t stop_time = curl_getdate(buf, &current_time);
+ if (stop_time == -1) {
+ this->StopTime = std::chrono::system_clock::time_point();
+ return;
+ }
+ this->StopTime = std::chrono::system_clock::from_time_t(stop_time);
+
+ if (stop_time < current_time) {
+ this->StopTime += std::chrono::hours(24);
+ }
}
int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
@@ -2274,7 +2307,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
std::string fname = dir;
fname += "/CTestCustom.cmake";
cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
- if (cmSystemTools::FileExists(fname.c_str())) {
+ if (cmSystemTools::FileExists(fname)) {
cmCTestLog(this, DEBUG, "* Read custom CTest configuration file: "
<< fname << std::endl);
bool erroroc = cmSystemTools::GetErrorOccuredFlag();
@@ -2294,7 +2327,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
std::string rexpr = dir;
rexpr += "/CTestCustom.ctest";
cmCTestLog(this, DEBUG, "* Check for file: " << rexpr << std::endl);
- if (!found && cmSystemTools::FileExists(rexpr.c_str())) {
+ if (!found && cmSystemTools::FileExists(rexpr)) {
cmsys::Glob gl;
gl.RecurseOn();
gl.FindFiles(rexpr);
@@ -2361,10 +2394,8 @@ std::string cmCTest::GetShortPathToFile(const char* cfname)
std::string fname = cmSystemTools::CollapseFullPath(cfname);
// Find relative paths to both directories
- std::string srcRelpath =
- cmSystemTools::RelativePath(sourceDir.c_str(), fname.c_str());
- std::string bldRelpath =
- cmSystemTools::RelativePath(buildDir.c_str(), fname.c_str());
+ std::string srcRelpath = cmSystemTools::RelativePath(sourceDir, fname);
+ std::string bldRelpath = cmSystemTools::RelativePath(buildDir, fname);
// If any contains "." it is not parent directory
bool inSrc = srcRelpath.find("..") == std::string::npos;
@@ -2418,38 +2449,6 @@ void cmCTest::EmptyCTestConfiguration()
this->CTestConfiguration.clear();
}
-void cmCTest::DetermineNextDayStop()
-{
- struct tm* lctime;
- time_t current_time = time(nullptr);
- lctime = gmtime(&current_time);
- int gm_hour = lctime->tm_hour;
- time_t gm_time = mktime(lctime);
- lctime = localtime(&current_time);
- int local_hour = lctime->tm_hour;
-
- int tzone_offset = local_hour - gm_hour;
- if (gm_time > current_time && gm_hour < local_hour) {
- // this means gm_time is on the next day
- tzone_offset -= 24;
- } else if (gm_time < current_time && gm_hour > local_hour) {
- // this means gm_time is on the previous day
- tzone_offset += 24;
- }
-
- tzone_offset *= 100;
- char buf[1024];
- sprintf(buf, "%d%02d%02d %s %+05i", lctime->tm_year + 1900,
- lctime->tm_mon + 1, lctime->tm_mday, this->StopTime.c_str(),
- tzone_offset);
-
- time_t stop_time = curl_getdate(buf, &current_time);
-
- if (stop_time < current_time) {
- this->NextDayStopTime = true;
- }
-}
-
void cmCTest::SetCTestConfiguration(const char* name, const char* value,
bool suppress)
{
@@ -2567,7 +2566,8 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable(
bool cmCTest::RunCommand(std::vector<std::string> const& args,
std::string* stdOut, std::string* stdErr, int* retVal,
- const char* dir, double timeout, Encoding encoding)
+ const char* dir, cmDuration timeout,
+ Encoding encoding)
{
std::vector<const char*> argv;
argv.reserve(args.size() + 1);
@@ -2585,7 +2585,7 @@ bool cmCTest::RunCommand(std::vector<std::string> const& args,
if (cmSystemTools::GetRunCommandHideConsole()) {
cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
}
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
std::vector<char> tempOutput;
@@ -2778,10 +2778,10 @@ void cmCTest::Log(int logType, const char* file, int line, const char* msg,
}
}
-double cmCTest::GetRemainingTimeAllowed()
+cmDuration cmCTest::GetRemainingTimeAllowed()
{
if (!this->GetHandler("script")) {
- return 1.0e7;
+ return cmCTest::MaxDuration();
}
cmCTestScriptHandler* ch =
@@ -2790,6 +2790,19 @@ double cmCTest::GetRemainingTimeAllowed()
return ch->GetRemainingTimeAllowed();
}
+cmDuration cmCTest::MaxDuration()
+{
+ return cmDuration(1.0e7);
+}
+
+void cmCTest::SetRunCurrentScript(bool value)
+{
+ cmCTestScriptHandler* ch =
+ static_cast<cmCTestScriptHandler*>(this->GetHandler("script"));
+
+ ch->SetRunCurrentScript(value);
+}
+
void cmCTest::OutputTestErrors(std::vector<char> const& process_output)
{
std::string test_outputs("\n*** Test Failed:\n");
diff --git a/Source/cmCTest.h b/Source/cmCTest.h
index dbd67dc68..673a40e5f 100644
--- a/Source/cmCTest.h
+++ b/Source/cmCTest.h
@@ -5,8 +5,10 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmDuration.h"
#include "cmProcessOutput.h"
#include "cmsys/String.hxx"
+#include <chrono>
#include <map>
#include <set>
#include <sstream>
@@ -139,10 +141,10 @@ public:
/** what is the configuraiton type, e.g. Debug, Release etc. */
std::string const& GetConfigType();
- double GetTimeOut() { return this->TimeOut; }
- void SetTimeOut(double t) { this->TimeOut = t; }
+ cmDuration GetTimeOut() { return this->TimeOut; }
+ void SetTimeOut(cmDuration t) { this->TimeOut = t; }
- double GetGlobalTimeout() { return this->GlobalTimeout; }
+ cmDuration GetGlobalTimeout() { return this->GlobalTimeout; }
/** how many test to run at the same time */
int GetParallelLevel() { return this->ParallelLevel; }
@@ -200,9 +202,11 @@ public:
/**
* Return the time remaining that the script is allowed to run in
* seconds if the user has set the variable CTEST_TIME_LIMIT. If that has
- * not been set it returns 1e7 seconds
+ * not been set it returns a very large duration.
*/
- double GetRemainingTimeAllowed();
+ cmDuration GetRemainingTimeAllowed();
+
+ static cmDuration MaxDuration();
/**
* Open file in the output directory and set the stream
@@ -220,7 +224,10 @@ public:
bool ShouldCompressTestOutput();
bool CompressString(std::string& str);
- std::string GetStopTime() { return this->StopTime; }
+ std::chrono::system_clock::time_point GetStopTime()
+ {
+ return this->StopTime;
+ }
void SetStopTime(std::string const& time);
/** Used for parallel ctest job scheduling */
@@ -248,7 +255,8 @@ public:
*/
bool RunCommand(std::vector<std::string> const& args, std::string* stdOut,
std::string* stdErr, int* retVal = nullptr,
- const char* dir = nullptr, double timeout = 0.0,
+ const char* dir = nullptr,
+ cmDuration timeout = cmDuration::zero(),
Encoding encoding = cmProcessOutput::Auto);
/**
@@ -268,7 +276,7 @@ public:
* and retVal is return value or exception.
*/
int RunMakeCommand(const char* command, std::string& output, int* retVal,
- const char* dir, int timeout, std::ostream& ofs,
+ const char* dir, cmDuration timeout, std::ostream& ofs,
Encoding encoding = cmProcessOutput::Auto);
/** Return the current tag */
@@ -315,7 +323,7 @@ public:
* environment variables are restored to their previous values.
*/
int RunTest(std::vector<const char*> args, std::string* output, int* retVal,
- std::ostream* logfile, double testTimeOut,
+ std::ostream* logfile, cmDuration testTimeOut,
std::vector<std::string>* environment,
Encoding encoding = cmProcessOutput::Auto);
@@ -420,9 +428,6 @@ public:
void SetFailover(bool failover) { this->Failover = failover; }
bool GetFailover() { return this->Failover; }
- void SetBatchJobs(bool batch = true) { this->BatchJobs = batch; }
- bool GetBatchJobs() { return this->BatchJobs; }
-
bool GetVerbose() { return this->Verbose; }
bool GetExtraVerbose() { return this->ExtraVerbose; }
@@ -453,13 +458,14 @@ public:
void GenerateSubprojectsOutput(cmXMLWriter& xml);
std::vector<std::string> GetLabelsForSubprojects();
+ void SetRunCurrentScript(bool value);
+
private:
int RepeatTests;
bool RepeatUntilFail;
std::string ConfigType;
std::string ScheduleType;
- std::string StopTime;
- bool NextDayStopTime;
+ std::chrono::system_clock::time_point StopTime;
bool Verbose;
bool ExtraVerbose;
bool ProduceXML;
@@ -468,7 +474,6 @@ private:
bool UseHTTP10;
bool PrintLabels;
bool Failover;
- bool BatchJobs;
bool ForceNewCTestProcess;
@@ -476,8 +481,6 @@ private:
int GenerateNotesFile(const char* files);
- void DetermineNextDayStop();
-
// these are helper classes
typedef std::map<std::string, cmCTestGenericHandler*> t_TestingHandlers;
t_TestingHandlers TestingHandlers;
@@ -487,7 +490,6 @@ private:
/** Map of configuration properties */
typedef std::map<std::string, std::string> CTestConfigurationMap;
- std::string CTestConfigFile;
// TODO: The ctest configuration should be a hierarchy of
// configuration option sources: command-line, script, ini file.
// Then the ini file can get re-loaded whenever it changes without
@@ -504,11 +506,9 @@ private:
int TestModel;
std::string SpecificTrack;
- double TimeOut;
-
- double GlobalTimeout;
+ cmDuration TimeOut;
- int LastStopTimeout;
+ cmDuration GlobalTimeout;
int MaxTestNameWidth;
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 44095ec14..fab2445ac 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -10,6 +10,7 @@
#include <string.h>
#include "cmGeneratedFileStream.h"
+#include "cmMessenger.h"
#include "cmState.h"
#include "cmSystemTools.h"
#include "cmVersion.h"
@@ -42,7 +43,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
if (internal) {
this->Cache.clear();
}
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (!cmSystemTools::FileExists(cacheFile)) {
this->CleanCMakeFiles(path);
return false;
}
@@ -205,7 +206,8 @@ bool cmCacheManager::ReadPropertyEntry(std::string const& entryKey,
return false;
}
-void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
+void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
+ cmMessenger* messenger)
{
for (const char** p = this->PersistentProperties; *p; ++p) {
if (const char* value = i.GetProperty(*p)) {
@@ -221,11 +223,13 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i)
os << ":INTERNAL=";
this->OutputValue(os, value);
os << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(os, key, value,
+ messenger);
}
}
}
-bool cmCacheManager::SaveCache(const std::string& path)
+bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
{
std::string cacheFile = path;
cacheFile += "/CMakeCache.txt";
@@ -316,7 +320,10 @@ bool cmCacheManager::SaveCache(const std::string& path)
this->OutputKey(fout, i.first);
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, ce.Value);
- fout << "\n\n";
+ fout << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(fout, i.first, ce.Value,
+ messenger);
+ fout << "\n";
}
}
@@ -333,7 +340,7 @@ bool cmCacheManager::SaveCache(const std::string& path)
}
cmStateEnums::CacheEntryType t = i.GetType();
- this->WritePropertyEntries(fout, i);
+ this->WritePropertyEntries(fout, i, messenger);
if (t == cmStateEnums::INTERNAL) {
// Format is key:type=value
if (const char* help = i.GetProperty("HELPSTRING")) {
@@ -343,13 +350,15 @@ bool cmCacheManager::SaveCache(const std::string& path)
fout << ":" << cmState::CacheEntryTypeToString(t) << "=";
this->OutputValue(fout, i.GetValue());
fout << "\n";
+ cmCacheManager::OutputNewlineTruncationWarning(fout, i.GetName(),
+ i.GetValue(), messenger);
}
}
fout << "\n";
fout.Close();
std::string checkCacheFile = path;
checkCacheFile += cmake::GetCMakeFilesDirectory();
- cmSystemTools::MakeDirectory(checkCacheFile.c_str());
+ cmSystemTools::MakeDirectory(checkCacheFile);
checkCacheFile += "/cmake.check_cache";
cmsys::ofstream checkCache(checkCacheFile.c_str());
if (!checkCache) {
@@ -368,7 +377,7 @@ bool cmCacheManager::DeleteCache(const std::string& path)
cmSystemTools::ConvertToUnixSlashes(cacheFile);
std::string cmakeFiles = cacheFile;
cacheFile += "/CMakeCache.txt";
- if (cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (cmSystemTools::FileExists(cacheFile)) {
cmSystemTools::RemoveFile(cacheFile);
// now remove the files in the CMakeFiles directory
// this cleans up language cache files
@@ -390,6 +399,19 @@ void cmCacheManager::OutputKey(std::ostream& fout, std::string const& key)
void cmCacheManager::OutputValue(std::ostream& fout, std::string const& value)
{
+ // look for and truncate newlines
+ std::string::size_type newline = value.find('\n');
+ if (newline != std::string::npos) {
+ std::string truncated = value.substr(0, newline);
+ OutputValueNoNewlines(fout, truncated);
+ } else {
+ OutputValueNoNewlines(fout, value);
+ }
+}
+
+void cmCacheManager::OutputValueNoNewlines(std::ostream& fout,
+ std::string const& value)
+{
// if value has trailing space or tab, enclose it in single quotes
if (!value.empty() &&
(value[value.size() - 1] == ' ' || value[value.size() - 1] == '\t')) {
@@ -423,6 +445,50 @@ void cmCacheManager::OutputHelpString(std::ostream& fout,
}
}
+void cmCacheManager::OutputWarningComment(std::ostream& fout,
+ std::string const& message,
+ bool wrapSpaces)
+{
+ std::string::size_type end = message.size();
+ std::string oneLine;
+ std::string::size_type pos = 0;
+ for (std::string::size_type i = 0; i <= end; i++) {
+ if ((i == end) || (message[i] == '\n') ||
+ ((i - pos >= 60) && (message[i] == ' ') && wrapSpaces)) {
+ fout << "# ";
+ if (message[pos] == '\n') {
+ pos++;
+ fout << "\\n";
+ }
+ oneLine = message.substr(pos, i - pos);
+ fout << oneLine << "\n";
+ pos = i;
+ }
+ }
+}
+
+void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout,
+ std::string const& key,
+ std::string const& value,
+ cmMessenger* messenger)
+{
+ if (value.find('\n') != std::string::npos) {
+ if (messenger) {
+ std::string message = "Value of ";
+ message += key;
+ message += " contained a newline; truncating";
+ messenger->IssueMessage(cmake::WARNING, message);
+ }
+
+ std::string comment = "WARNING: Value of ";
+ comment += key;
+ comment += " contained a newline and was truncated. Original value:";
+
+ OutputWarningComment(fout, comment, true);
+ OutputWarningComment(fout, value, false);
+ }
+}
+
void cmCacheManager::RemoveCacheEntry(const std::string& key)
{
CacheEntryMap::iterator i = this->Cache.find(key);
diff --git a/Source/cmCacheManager.h b/Source/cmCacheManager.h
index e9e6570ef..73923d1f5 100644
--- a/Source/cmCacheManager.h
+++ b/Source/cmCacheManager.h
@@ -15,7 +15,7 @@
#include "cmPropertyMap.h"
#include "cmStateTypes.h"
-class cmake;
+class cmMessenger;
/** \class cmCacheManager
* \brief Control class for cmake's cache
@@ -107,8 +107,8 @@ public:
std::set<std::string>& excludes,
std::set<std::string>& includes);
- ///! Save cache for given makefile. Saves to ouput path/CMakeCache.txt
- bool SaveCache(const std::string& path);
+ ///! Save cache for given makefile. Saves to output path/CMakeCache.txt
+ bool SaveCache(const std::string& path, cmMessenger* messenger);
///! Delete the cache given
bool DeleteCache(const std::string& path);
@@ -218,16 +218,25 @@ protected:
unsigned int CacheMinorVersion;
private:
- cmake* CMakeInstance;
typedef std::map<std::string, CacheEntry> CacheEntryMap;
static void OutputHelpString(std::ostream& fout,
const std::string& helpString);
+ static void OutputWarningComment(std::ostream& fout,
+ std::string const& message,
+ bool wrapSpaces);
+ static void OutputNewlineTruncationWarning(std::ostream& fout,
+ std::string const& key,
+ std::string const& value,
+ cmMessenger* messenger);
static void OutputKey(std::ostream& fout, std::string const& key);
static void OutputValue(std::ostream& fout, std::string const& value);
+ static void OutputValueNoNewlines(std::ostream& fout,
+ std::string const& value);
static const char* PersistentProperties[];
bool ReadPropertyEntry(std::string const& key, CacheEntry& e);
- void WritePropertyEntries(std::ostream& os, CacheIterator i);
+ void WritePropertyEntries(std::ostream& os, CacheIterator i,
+ cmMessenger* messenger);
CacheEntryMap Cache;
// Only cmake and cmState should be able to add cache values
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 6ae58d67a..bf314bddf 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -21,13 +21,6 @@ cmCommandArgumentParserHelper::cmCommandArgumentParserHelper()
this->FileLine = -1;
this->FileName = nullptr;
this->RemoveEmpty = true;
- this->EmptyVariable[0] = 0;
- strcpy(this->DCURLYVariable, "${");
- strcpy(this->RCURLYVariable, "}");
- strcpy(this->ATVariable, "@");
- strcpy(this->DOLLARVariable, "$");
- strcpy(this->LCURLYVariable, "{");
- strcpy(this->BSLASHVariable, "\\");
this->NoEscapeMode = false;
this->ReplaceAtSyntax = false;
@@ -44,10 +37,10 @@ void cmCommandArgumentParserHelper::SetLineFile(long line, const char* file)
this->FileName = file;
}
-char* cmCommandArgumentParserHelper::AddString(const std::string& str)
+const char* cmCommandArgumentParserHelper::AddString(const std::string& str)
{
if (str.empty()) {
- return this->EmptyVariable;
+ return "";
}
char* stVal = new char[str.size() + 1];
strcpy(stVal, str.c_str());
@@ -55,14 +48,14 @@ char* cmCommandArgumentParserHelper::AddString(const std::string& str)
return stVal;
}
-char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
- const char* var)
+const char* cmCommandArgumentParserHelper::ExpandSpecialVariable(
+ const char* key, const char* var)
{
if (!key) {
return this->ExpandVariable(var);
}
if (!var) {
- return this->EmptyVariable;
+ return "";
}
if (strcmp(key, "ENV") == 0) {
std::string str;
@@ -72,7 +65,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
}
return this->AddString(str);
}
- return this->EmptyVariable;
+ return "";
}
if (strcmp(key, "CACHE") == 0) {
if (const char* c =
@@ -82,7 +75,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
}
return this->AddString(c);
}
- return this->EmptyVariable;
+ return "";
}
std::ostringstream e;
e << "Syntax $" << key << "{} is not supported. "
@@ -91,7 +84,7 @@ char* cmCommandArgumentParserHelper::ExpandSpecialVariable(const char* key,
return nullptr;
}
-char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
+const char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
{
if (!var) {
return nullptr;
@@ -125,11 +118,11 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var)
return this->AddString(value ? value : "");
}
-char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
+const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
{
if (this->ReplaceAtSyntax) {
// try to expand the variable
- char* ret = this->ExpandVariable(var);
+ const char* ret = this->ExpandVariable(var);
// if the return was 0 and we want to replace empty strings
// then return an empty string
if (!ret && this->RemoveEmpty) {
@@ -150,7 +143,8 @@ char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
return this->AddString(ref);
}
-char* cmCommandArgumentParserHelper::CombineUnions(char* in1, char* in2)
+const char* cmCommandArgumentParserHelper::CombineUnions(const char* in1,
+ const char* in2)
{
if (!in1) {
return in2;
@@ -176,10 +170,11 @@ void cmCommandArgumentParserHelper::AllocateParserType(
if (len == 0) {
return;
}
- pt->str = new char[len + 1];
- strncpy(pt->str, str, len);
- pt->str[len] = 0;
- this->Variables.push_back(pt->str);
+ char* out = new char[len + 1];
+ strncpy(out, str, len);
+ out[len] = 0;
+ pt->str = out;
+ this->Variables.push_back(out);
}
bool cmCommandArgumentParserHelper::HandleEscapeSymbol(
diff --git a/Source/cmCommandArgumentParserHelper.h b/Source/cmCommandArgumentParserHelper.h
index cb2a39074..098c00064 100644
--- a/Source/cmCommandArgumentParserHelper.h
+++ b/Source/cmCommandArgumentParserHelper.h
@@ -17,7 +17,7 @@ class cmCommandArgumentParserHelper
public:
struct ParserType
{
- char* str;
+ const char* str;
};
cmCommandArgumentParserHelper();
@@ -35,11 +35,11 @@ public:
void Error(const char* str);
// For yacc
- char* CombineUnions(char* in1, char* in2);
+ const char* CombineUnions(const char* in1, const char* in2);
- char* ExpandSpecialVariable(const char* key, const char* var);
- char* ExpandVariable(const char* var);
- char* ExpandVariableForAt(const char* var);
+ const char* ExpandSpecialVariable(const char* key, const char* var);
+ const char* ExpandVariable(const char* var);
+ const char* ExpandVariableForAt(const char* var);
void SetResult(const char* value);
void SetMakefile(const cmMakefile* mf);
@@ -53,13 +53,6 @@ public:
void SetRemoveEmpty(bool b) { this->RemoveEmpty = b; }
const char* GetError() { return this->ErrorString.c_str(); }
- char EmptyVariable[1];
- char DCURLYVariable[3];
- char RCURLYVariable[3];
- char ATVariable[3];
- char DOLLARVariable[3];
- char LCURLYVariable[3];
- char BSLASHVariable[3];
private:
std::string::size_type InputBufferPos;
@@ -69,7 +62,7 @@ private:
void Print(const char* place, const char* str);
void SafePrintMissing(const char* str, int line, int cnt);
- char* AddString(const std::string& str);
+ const char* AddString(const std::string& str);
void CleanupParser();
void SetError(std::string const& msg);
diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx
index 8a7d9bde7..a1de8b178 100644
--- a/Source/cmCommands.cxx
+++ b/Source/cmCommands.cxx
@@ -343,7 +343,7 @@ void GetProjectCommandsInScriptMode(cmState* state)
CM_UNEXPECTED_PROJECT_COMMAND("try_compile");
CM_UNEXPECTED_PROJECT_COMMAND("try_run");
- // deprected commands
+ // deprecated commands
CM_UNEXPECTED_PROJECT_COMMAND("export_library_dependencies");
CM_UNEXPECTED_PROJECT_COMMAND("load_command");
CM_UNEXPECTED_PROJECT_COMMAND("output_required_files");
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 1189606fc..d6d8eb060 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -159,7 +159,7 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
std::string di = lg->GetCurrentBinaryDirectory();
di += "/";
di += lg->GetTargetDirectory(linkee);
- dirs.push_back(di);
+ dirs.push_back(std::move(di));
}
}
}
diff --git a/Source/cmComputeComponentGraph.cxx b/Source/cmComputeComponentGraph.cxx
index 9ec98ae8e..a7dc1ca03 100644
--- a/Source/cmComputeComponentGraph.cxx
+++ b/Source/cmComputeComponentGraph.cxx
@@ -88,7 +88,7 @@ void cmComputeComponentGraph::TarjanVisit(int i)
if (this->TarjanEntries[i].Root == i) {
// Yes. Create it.
int c = static_cast<int>(this->Components.size());
- this->Components.push_back(NodeList());
+ this->Components.emplace_back();
NodeList& component = this->Components[c];
// Populate the component list.
@@ -125,8 +125,8 @@ void cmComputeComponentGraph::TransferEdges()
if (i_component != j_component) {
// We do not attempt to combine duplicate edges, but instead
// store the inter-component edges with suitable multiplicity.
- this->ComponentGraph[i_component].push_back(
- cmGraphEdge(j_component, ni.IsStrong()));
+ this->ComponentGraph[i_component].emplace_back(j_component,
+ ni.IsStrong());
}
}
}
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index d9efc2e33..354de366e 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -285,9 +285,9 @@ std::map<std::string, int>::iterator cmComputeLinkDepends::AllocateLinkEntry(
item, static_cast<int>(this->EntryList.size()));
std::map<std::string, int>::iterator lei =
this->LinkEntryIndex.insert(index_entry).first;
- this->EntryList.push_back(LinkEntry());
+ this->EntryList.emplace_back();
this->InferredDependSets.push_back(nullptr);
- this->EntryConstraintGraph.push_back(EdgeList());
+ this->EntryConstraintGraph.emplace_back();
return lei;
}
@@ -472,8 +472,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
// If the library is meant for this link type then use it.
if (llt == GENERAL_LibraryType || llt == this->LinkType) {
- cmLinkItem item(d, this->FindTargetToLink(depender_index, d));
- actual_libs.push_back(item);
+ actual_libs.emplace_back(d, this->FindTargetToLink(depender_index, d));
} else if (this->OldLinkDirMode) {
cmLinkItem item(d, this->FindTargetToLink(depender_index, d));
this->CheckWrongConfigItem(item);
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index fb13a585b..8a5a6de6c 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -498,8 +498,8 @@ bool cmComputeLinkInformation::Compute()
cmStateEnums::ArtifactType artifact = implib
? cmStateEnums::ImportLibraryArtifact
: cmStateEnums::RuntimeBinaryArtifact;
- std::string lib = tgt->GetFullPath(this->Config, artifact, true);
- this->OldLinkDirItems.push_back(lib);
+ this->OldLinkDirItems.push_back(
+ tgt->GetFullPath(this->Config, artifact, true));
}
}
@@ -598,13 +598,13 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
std::string exe = tgt->GetFullPath(config, artifact, true);
linkItem += exe;
- this->Items.push_back(Item(linkItem, true, tgt));
- this->Depends.push_back(exe);
+ this->Items.emplace_back(linkItem, true, tgt);
+ this->Depends.push_back(std::move(exe));
} else if (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
// Add the interface library as an item so it can be considered as part
// of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore
// this for the actual link line.
- this->Items.push_back(Item(std::string(), false, tgt));
+ this->Items.emplace_back(std::string(), false, tgt);
// Also add the item the interface specifies to be used in its place.
std::string const& libName = tgt->GetImportedLibName(config);
@@ -632,7 +632,7 @@ void cmComputeLinkInformation::AddItem(std::string const& item,
}
} else {
// This is not a CMake target. Use the name given.
- if (cmSystemTools::FileIsFullPath(item.c_str())) {
+ if (cmSystemTools::FileIsFullPath(item)) {
if (cmSystemTools::FileIsDirectory(item)) {
// This is a directory.
this->AddDirectoryItem(item);
@@ -668,13 +668,13 @@ void cmComputeLinkInformation::AddSharedDepItem(std::string const& item,
} else {
// Skip items that are not full paths. We will not be able to
// reliably specify them.
- if (!cmSystemTools::FileIsFullPath(item.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(item)) {
return;
}
// Get the name of the library from the file name.
std::string file = cmSystemTools::GetFilenameName(item);
- if (!this->ExtractSharedLibraryName.find(file.c_str())) {
+ if (!this->ExtractSharedLibraryName.find(file)) {
// This is not the name of a shared library.
return;
}
@@ -913,11 +913,9 @@ std::string cmComputeLinkInformation::CreateExtensionRegex(
// Finish the list.
libext += ")";
- // Add an optional OpenBSD version component.
- if (this->OpenBSD) {
- libext += "(\\.[0-9]+\\.[0-9]+)?";
- } else if (type == LinkShared) {
- libext += "(\\.[0-9]+)?";
+ // Add an optional OpenBSD-style version or major.minor.version component.
+ if (this->OpenBSD || type == LinkShared) {
+ libext += "(\\.[0-9]+)*";
}
libext += "$";
@@ -952,10 +950,10 @@ void cmComputeLinkInformation::SetCurrentLinkType(LinkType lt)
if (this->LinkTypeEnabled) {
switch (this->CurrentLinkType) {
case LinkStatic:
- this->Items.push_back(Item(this->StaticLinkTypeFlag, false));
+ this->Items.emplace_back(this->StaticLinkTypeFlag, false);
break;
case LinkShared:
- this->Items.push_back(Item(this->SharedLinkTypeFlag, false));
+ this->Items.emplace_back(this->SharedLinkTypeFlag, false);
break;
default:
break;
@@ -991,7 +989,7 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
// If this platform wants a flag before the full path, add it.
if (!this->LibLinkFileFlag.empty()) {
- this->Items.push_back(Item(this->LibLinkFileFlag, false));
+ this->Items.emplace_back(this->LibLinkFileFlag, false);
}
// For compatibility with CMake 2.4 include the item's directory in
@@ -1003,7 +1001,7 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item,
}
// Now add the full path to the library.
- this->Items.push_back(Item(item, true, target));
+ this->Items.emplace_back(item, true, target);
}
void cmComputeLinkInformation::AddFullItem(std::string const& item)
@@ -1058,11 +1056,11 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item)
// If this platform wants a flag before the full path, add it.
if (!this->LibLinkFileFlag.empty()) {
- this->Items.push_back(Item(this->LibLinkFileFlag, false));
+ this->Items.emplace_back(this->LibLinkFileFlag, false);
}
// Now add the full path to the library.
- this->Items.push_back(Item(item, true));
+ this->Items.emplace_back(item, true);
}
bool cmComputeLinkInformation::CheckImplicitDirItem(std::string const& item)
@@ -1149,7 +1147,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
this->SetCurrentLinkType(this->StartLinkType);
// Use the item verbatim.
- this->Items.push_back(Item(item, false));
+ this->Items.emplace_back(item, false);
return;
}
@@ -1221,7 +1219,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
std::string out = this->LibLinkFlag;
out += lib;
out += this->LibLinkSuffix;
- this->Items.push_back(Item(out, false));
+ this->Items.emplace_back(out, false);
// Here we could try to find the library the linker will find and
// add a runtime information entry for it. It would probably not be
@@ -1256,10 +1254,10 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
this->AddLibraryRuntimeInfo(full_fw);
// Add the item using the -framework option.
- this->Items.push_back(Item("-framework", false));
+ this->Items.emplace_back("-framework", false);
cmOutputConverter converter(this->Makefile->GetStateSnapshot());
fw = converter.EscapeForShell(fw);
- this->Items.push_back(Item(fw, false));
+ this->Items.emplace_back(fw, false);
}
void cmComputeLinkInformation::AddDirectoryItem(std::string const& item)
@@ -1744,12 +1742,13 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
cmSystemTools::ConvertToUnixSlashes(d);
}
if (emitted.insert(d).second) {
- runtimeDirs.push_back(d);
+ runtimeDirs.push_back(std::move(d));
}
} else if (use_link_rpath) {
// Do not add any path inside the source or build tree.
- const char* topSourceDir = this->CMakeInstance->GetHomeDirectory();
- const char* topBinaryDir =
+ std::string const& topSourceDir =
+ this->CMakeInstance->GetHomeDirectory();
+ std::string const& topBinaryDir =
this->CMakeInstance->GetHomeOutputDirectory();
if (!cmSystemTools::ComparePath(ri, topSourceDir) &&
!cmSystemTools::ComparePath(ri, topBinaryDir) &&
@@ -1766,7 +1765,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
cmSystemTools::ConvertToUnixSlashes(d);
}
if (emitted.insert(d).second) {
- runtimeDirs.push_back(d);
+ runtimeDirs.push_back(std::move(d));
}
}
}
diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx
index 963c2df88..18767a362 100644
--- a/Source/cmComputeTargetDepends.cxx
+++ b/Source/cmComputeTargetDepends.cxx
@@ -200,7 +200,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index)
std::vector<std::string> configs;
depender->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
for (std::string const& it : configs) {
std::vector<cmSourceFile const*> objectFiles;
@@ -369,8 +369,7 @@ void cmComputeTargetDepends::AddTargetDepend(int depender_index,
int dependee_index = tii->second;
// Add this entry to the dependency graph.
- this->InitialGraph[depender_index].push_back(
- cmGraphEdge(dependee_index, !linking));
+ this->InitialGraph[depender_index].emplace_back(dependee_index, !linking);
}
}
@@ -504,7 +503,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
for (cmGraphEdge const& edge : el) {
int j = edge;
if (cmap[j] == c && edge.IsStrong()) {
- this->FinalGraph[i].push_back(cmGraphEdge(j, true));
+ this->FinalGraph[i].emplace_back(j, true);
if (!this->IntraComponent(cmap, c, j, head, emitted, visited)) {
return false;
}
@@ -513,7 +512,7 @@ bool cmComputeTargetDepends::IntraComponent(std::vector<int> const& cmap,
// Prepend to a linear linked-list of intra-component edges.
if (*head >= 0) {
- this->FinalGraph[i].push_back(cmGraphEdge(*head, false));
+ this->FinalGraph[i].emplace_back(*head, false);
} else {
this->ComponentTail[c] = i;
}
@@ -563,8 +562,8 @@ bool cmComputeTargetDepends::ComputeFinalDepends(
for (cmGraphEdge const& ni : nl) {
int dependee_component = ni;
int dependee_component_head = this->ComponentHead[dependee_component];
- this->FinalGraph[depender_component_tail].push_back(
- cmGraphEdge(dependee_component_head, ni.IsStrong()));
+ this->FinalGraph[depender_component_tail].emplace_back(
+ dependee_component_head, ni.IsStrong());
}
}
return true;
diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx
index 90b3f6d9a..172ef9247 100644
--- a/Source/cmConditionEvaluator.cxx
+++ b/Source/cmConditionEvaluator.cxx
@@ -494,7 +494,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList& newArgs, std::string&,
if (argP1len > 4 && argP1->GetValue().substr(0, 4) == "ENV{" &&
argP1->GetValue().operator[](argP1len - 1) == '}') {
std::string env = argP1->GetValue().substr(4, argP1len - 5);
- bdef = cmSystemTools::HasEnv(env.c_str());
+ bdef = cmSystemTools::HasEnv(env);
} else {
bdef = this->Makefile.IsDefinitionSet(argP1->GetValue());
}
diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in
index 9a78aca36..c80439b13 100644
--- a/Source/cmConfigure.cmake.h.in
+++ b/Source/cmConfigure.cmake.h.in
@@ -19,22 +19,11 @@
#cmakedefine HAVE_UNSETENV
#cmakedefine CMAKE_USE_ELF_PARSER
#cmakedefine CMAKE_USE_MACH_PARSER
-#cmakedefine CMake_HAVE_CXX_FALLTHROUGH
-#cmakedefine CMake_HAVE_CXX_GNU_FALLTHROUGH
-#cmakedefine CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH
#cmakedefine CMake_HAVE_CXX_MAKE_UNIQUE
#define CMAKE_BIN_DIR "/@CMAKE_BIN_DIR@"
#define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@"
-#if defined(CMake_HAVE_CXX_FALLTHROUGH)
-#define CM_FALLTHROUGH [[fallthrough]]
-#elif defined(CMake_HAVE_CXX_GNU_FALLTHROUGH)
-#define CM_FALLTHROUGH [[gnu::fallthrough]]
-#elif defined(CMake_HAVE_CXX_ATTRIBUTE_FALLTHROUGH)
-#define CM_FALLTHROUGH __attribute__((fallthrough))
-#else
-#define CM_FALLTHROUGH
-#endif
+#define CM_FALLTHROUGH cmsys_FALLTHROUGH
#define CM_DISABLE_COPY(Class) \
Class(Class const&) = delete; \
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index 18005f27c..b5a639ac5 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -51,7 +51,7 @@ bool cmConfigureFileCommand::InitialPass(std::vector<std::string> const& args,
this->OutputFile += cmSystemTools::GetFilenameName(inFile);
}
- if (!this->Makefile->CanIWriteThisFile(this->OutputFile.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(this->OutputFile)) {
std::string e = "attempted to configure a file: " + this->OutputFile +
" into a source directory.";
this->SetError(e);
diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx
index 28ba12c4b..50e193668 100644
--- a/Source/cmConnection.cxx
+++ b/Source/cmConnection.cxx
@@ -26,7 +26,7 @@ void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle,
void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread,
const uv_buf_t* buf)
{
- auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data);
+ auto conn = static_cast<cmEventBasedConnection*>(stream->data);
if (conn) {
if (nread >= 0) {
conn->ReadData(std::string(buf->base, buf->base + nread));
@@ -55,7 +55,7 @@ void cmEventBasedConnection::on_write(uv_write_t* req, int status)
void cmEventBasedConnection::on_new_connection(uv_stream_t* stream, int status)
{
(void)(status);
- auto conn = reinterpret_cast<cmEventBasedConnection*>(stream->data);
+ auto conn = static_cast<cmEventBasedConnection*>(stream->data);
if (conn) {
conn->Connect(stream);
@@ -76,7 +76,7 @@ void cmEventBasedConnection::WriteData(const std::string& _data)
#endif
auto data = _data;
- assert(this->WriteStream);
+ assert(this->WriteStream.get());
if (BufferStrategy) {
data = BufferStrategy->BufferOutMessage(data);
}
@@ -87,8 +87,7 @@ void cmEventBasedConnection::WriteData(const std::string& _data)
req->req.data = this;
req->buf = uv_buf_init(new char[ds], static_cast<unsigned int>(ds));
memcpy(req->buf.base, data.c_str(), ds);
- uv_write(reinterpret_cast<uv_write_t*>(req),
- static_cast<uv_stream_t*>(this->WriteStream), &req->buf, 1,
+ uv_write(reinterpret_cast<uv_write_t*>(req), this->WriteStream, &req->buf, 1,
on_write);
}
@@ -156,13 +155,11 @@ bool cmConnection::OnServeStart(std::string* errString)
bool cmEventBasedConnection::OnConnectionShuttingDown()
{
- if (this->WriteStream) {
+ if (this->WriteStream.get()) {
this->WriteStream->data = nullptr;
}
- if (this->ReadStream) {
- this->ReadStream->data = nullptr;
- }
- this->ReadStream = nullptr;
- this->WriteStream = nullptr;
+
+ WriteStream.reset();
+
return true;
}
diff --git a/Source/cmConnection.h b/Source/cmConnection.h
index ddb774457..ce2d2dc2a 100644
--- a/Source/cmConnection.h
+++ b/Source/cmConnection.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmUVHandlePtr.h"
#include "cm_uv.h"
#include <cstddef>
@@ -107,8 +108,6 @@ public:
bool OnConnectionShuttingDown() override;
virtual void OnDisconnect(int errorCode);
- uv_stream_t* ReadStream = nullptr;
- uv_stream_t* WriteStream = nullptr;
static void on_close(uv_handle_t* handle);
@@ -119,6 +118,8 @@ public:
}
protected:
+ cm::uv_stream_ptr WriteStream;
+
std::string RawReadBuffer;
std::unique_ptr<cmConnectionBufferStrategy> BufferStrategy;
diff --git a/Source/cmConvertMSBuildXMLToJSON.py b/Source/cmConvertMSBuildXMLToJSON.py
index 93ab8a82f..92569e744 100644
--- a/Source/cmConvertMSBuildXMLToJSON.py
+++ b/Source/cmConvertMSBuildXMLToJSON.py
@@ -343,7 +343,7 @@ def __with_argument(node, value):
def __preprocess_arguments(root):
- """Preprocesses occurrances of Argument within the root.
+ """Preprocesses occurrences of Argument within the root.
Argument XML values reference other values within the document by name. The
referenced value does not contain a switch. This function will add the
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index fd258fe79..26e0db9e2 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -391,7 +391,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
}
}
// make sure the binary directory exists
- cmSystemTools::MakeDirectory(this->BinaryDirectory.c_str());
+ cmSystemTools::MakeDirectory(this->BinaryDirectory);
// do not allow recursive try Compiles
if (this->BinaryDirectory == this->Makefile->GetHomeOutputDirectory()) {
@@ -580,7 +580,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
if (!targets.empty()) {
std::string fname = "/" + std::string(targetName) + "Targets.cmake";
- cmExportTryCompileFileGenerator tcfg(gg, targets, this->Makefile);
+ cmExportTryCompileFileGenerator tcfg(gg, targets, this->Makefile,
+ testLangs);
tcfg.SetExportFile((this->BinaryDirectory + fname).c_str());
tcfg.SetConfig(tcConfig);
@@ -631,13 +632,13 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
kCMAKE_TRY_COMPILE_OSX_ARCHITECTURES)) {
vars.erase(kCMAKE_OSX_ARCHITECTURES);
std::string flag = "-DCMAKE_OSX_ARCHITECTURES=" + std::string(tcArchs);
- cmakeFlags.push_back(flag);
+ cmakeFlags.push_back(std::move(flag));
}
for (std::string const& var : vars) {
if (const char* val = this->Makefile->GetDefinition(var)) {
std::string flag = "-D" + var + "=" + val;
- cmakeFlags.push_back(flag);
+ cmakeFlags.push_back(std::move(flag));
}
}
}
@@ -864,18 +865,17 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv,
return res;
}
-void cmCoreTryCompile::CleanupFiles(const char* binDir)
+void cmCoreTryCompile::CleanupFiles(std::string const& binDir)
{
- if (!binDir) {
+ if (binDir.empty()) {
return;
}
- std::string bdir = binDir;
- if (bdir.find("CMakeTmp") == std::string::npos) {
+ if (binDir.find("CMakeTmp") == std::string::npos) {
cmSystemTools::Error(
"TRY_COMPILE attempt to remove -rf directory that does not contain "
"CMakeTmp:",
- binDir);
+ binDir.c_str());
return;
}
@@ -889,7 +889,7 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
std::string const fullPath =
std::string(binDir).append("/").append(fileName);
if (cmSystemTools::FileIsDirectory(fullPath)) {
- this->CleanupFiles(fullPath.c_str());
+ this->CleanupFiles(fullPath);
cmSystemTools::RemoveADirectory(fullPath);
} else {
#ifdef _WIN32
@@ -897,9 +897,8 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
// cannot delete them immediately. Try a few times.
cmSystemTools::WindowsFileRetry retry =
cmSystemTools::GetWindowsFileRetry();
- while (!cmSystemTools::RemoveFile(fullPath.c_str()) &&
- --retry.Count &&
- cmSystemTools::FileExists(fullPath.c_str())) {
+ while (!cmSystemTools::RemoveFile(fullPath) && --retry.Count &&
+ cmSystemTools::FileExists(fullPath)) {
cmSystemTools::Delay(retry.Delay);
}
if (retry.Count == 0)
@@ -938,7 +937,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
// a list of directories where to search for the compilation result
// at first directly in the binary dir
std::vector<std::string> searchDirs;
- searchDirs.push_back("");
+ searchDirs.emplace_back();
const char* config =
this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
@@ -946,12 +945,12 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
if (config && config[0]) {
std::string tmp = "/";
tmp += config;
- searchDirs.push_back(tmp);
+ searchDirs.push_back(std::move(tmp));
}
searchDirs.push_back("/Debug");
#if defined(__APPLE__)
std::string app = "/Debug/" + targetName + ".app";
- searchDirs.push_back(app);
+ searchDirs.push_back(std::move(app));
#endif
searchDirs.push_back("/Development");
@@ -959,7 +958,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
std::string command = this->BinaryDirectory;
command += sdir;
command += tmpOutputFile;
- if (cmSystemTools::FileExists(command.c_str())) {
+ if (cmSystemTools::FileExists(command)) {
this->OutputFile = cmSystemTools::CollapseFullPath(command);
return;
}
diff --git a/Source/cmCoreTryCompile.h b/Source/cmCoreTryCompile.h
index 365154dfb..6f35a540f 100644
--- a/Source/cmCoreTryCompile.h
+++ b/Source/cmCoreTryCompile.h
@@ -33,7 +33,7 @@ protected:
* This way we do not have to rely on the timing and
* dependencies of makefiles.
*/
- void CleanupFiles(const char* binDir);
+ void CleanupFiles(std::string const& binDir);
/**
* This tries to find the (executable) file created by
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 341b8c077..8ef8bffe8 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -56,3 +56,41 @@ std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile)
#endif
return e;
}
+
+std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
+ const std::string& netrc_file)
+{
+ std::string e;
+ CURL_NETRC_OPTION curl_netrc_level = CURL_NETRC_LAST;
+ ::CURLcode res;
+
+ if (!netrc_level.empty()) {
+ if (netrc_level == "OPTIONAL") {
+ curl_netrc_level = CURL_NETRC_OPTIONAL;
+ } else if (netrc_level == "REQUIRED") {
+ curl_netrc_level = CURL_NETRC_REQUIRED;
+ } else if (netrc_level == "IGNORED") {
+ curl_netrc_level = CURL_NETRC_IGNORED;
+ } else {
+ e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ";
+ e += netrc_level;
+ return e;
+ }
+ }
+
+ if (curl_netrc_level != CURL_NETRC_LAST &&
+ curl_netrc_level != CURL_NETRC_IGNORED) {
+ res = ::curl_easy_setopt(curl, CURLOPT_NETRC, curl_netrc_level);
+ check_curl_result(res, "Unable to set netrc level: ");
+ if (!e.empty()) {
+ return e;
+ }
+
+ // check to see if a .netrc file has been specified
+ if (!netrc_file.empty()) {
+ res = ::curl_easy_setopt(curl, CURLOPT_NETRC_FILE, netrc_file.c_str());
+ check_curl_result(res, "Unable to set .netrc file path : ");
+ }
+ }
+ return e;
+}
diff --git a/Source/cmCurl.h b/Source/cmCurl.h
index 0688bb2d7..fe7eb809f 100644
--- a/Source/cmCurl.h
+++ b/Source/cmCurl.h
@@ -9,5 +9,7 @@
#include <string>
std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr);
+std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
+ const std::string& netrc_file);
#endif
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 3d816d562..136cf39be 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -8,12 +8,12 @@
#include "cmGeneratorTarget.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
-#include "cmOutputConverter.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include <memory> // IWYU pragma: keep
#include <stddef.h>
+#include <utility>
cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
const std::string& config,
@@ -37,10 +37,10 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
cmSystemTools::ExpandListArgument(parsed_arg, ExpandedArg);
argv.insert(argv.end(), ExpandedArg.begin(), ExpandedArg.end());
} else {
- argv.push_back(parsed_arg);
+ argv.push_back(std::move(parsed_arg));
}
}
- this->CommandLines.push_back(argv);
+ this->CommandLines.push_back(std::move(argv));
}
std::vector<std::string> depends = this->CC.GetDepends();
@@ -50,7 +50,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(cmCustomCommand const& cc,
cmSystemTools::ExpandListArgument(cge->Evaluate(this->LG, this->Config),
result);
for (std::string& it : result) {
- if (cmSystemTools::FileIsFullPath(it.c_str())) {
+ if (cmSystemTools::FileIsFullPath(it)) {
it = cmSystemTools::CollapseFullPath(it);
}
}
@@ -166,8 +166,7 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
if (this->OldStyle) {
cmd += escapeForShellOldStyle(arg);
} else {
- cmOutputConverter converter(this->LG->GetStateSnapshot());
- cmd += converter.EscapeForShell(arg, this->MakeVars);
+ cmd += this->LG->EscapeForShell(arg, this->MakeVars);
}
}
}
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 1ab3fa244..62bc8d9ef 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -131,14 +131,12 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// If not a full path, find the file in the include path.
std::string fullName;
- if ((srcFiles > 0) ||
- cmSystemTools::FileIsFullPath(current.FileName.c_str())) {
- if (cmSystemTools::FileExists(current.FileName.c_str(), true)) {
+ if ((srcFiles > 0) || cmSystemTools::FileIsFullPath(current.FileName)) {
+ if (cmSystemTools::FileExists(current.FileName, true)) {
fullName = current.FileName;
}
} else if (!current.QuotedLocation.empty() &&
- cmSystemTools::FileExists(current.QuotedLocation.c_str(),
- true)) {
+ cmSystemTools::FileExists(current.QuotedLocation, true)) {
// The include statement producing this entry was a double-quote
// include and the included file is present in the directory of
// the source containing the include statement.
@@ -157,7 +155,7 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
cmSystemTools::CollapseCombinedPath(i, current.FileName);
// Look for the file in this location.
- if (cmSystemTools::FileExists(tempPathStr.c_str(), true)) {
+ if (cmSystemTools::FileExists(tempPathStr, true)) {
fullName = tempPathStr;
HeaderLocationCache[current.FileName] = fullName;
break;
@@ -226,15 +224,14 @@ bool cmDependsC::WriteDependencies(const std::set<std::string>& sources,
// directory. We must do the same here.
std::string binDir = this->LocalGenerator->GetBinaryDirectory();
std::string obj_i = this->LocalGenerator->ConvertToRelativePath(binDir, obj);
- std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str());
+ std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << std::endl;
for (std::string const& dep : dependencies) {
- makeDepends
- << obj_m << ": "
- << cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator->ConvertToRelativePath(binDir, dep).c_str())
- << std::endl;
+ makeDepends << obj_m << ": "
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->ConvertToRelativePath(binDir, dep))
+ << std::endl;
internalDepends << " " << dep << std::endl;
}
makeDepends << std::endl;
@@ -303,7 +300,7 @@ void cmDependsC::ReadCacheFile()
if (line != "-") {
entry.QuotedLocation = line;
}
- cacheEntry->UnscannedEntries.push_back(entry);
+ cacheEntry->UnscannedEntries.push_back(std::move(entry));
}
}
}
@@ -363,7 +360,7 @@ void cmDependsC::Scan(std::istream& is, const char* directory,
entry.FileName = this->IncludeRegexLine.match(2);
cmSystemTools::ConvertToUnixSlashes(entry.FileName);
if (this->IncludeRegexLine.match(3) == "\"" &&
- !cmSystemTools::FileIsFullPath(entry.FileName.c_str())) {
+ !cmSystemTools::FileIsFullPath(entry.FileName)) {
// This was a double-quoted include with a relative path. We
// must check for the file in the directory containing the
// file we are scanning.
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index fdbc08627..1a66ca026 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -312,13 +312,13 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
// Write the include dependencies to the output stream.
std::string binDir = this->LocalGenerator->GetBinaryDirectory();
std::string obj_i = this->MaybeConvertToRelativePath(binDir, obj);
- std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i.c_str());
+ std::string obj_m = cmSystemTools::ConvertToOutputPath(obj_i);
internalDepends << obj_i << std::endl;
internalDepends << " " << src << std::endl;
for (std::string const& i : info.Includes) {
makeDepends << obj_m << ": "
<< cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, i).c_str())
+ this->MaybeConvertToRelativePath(binDir, i))
<< std::endl;
internalDepends << " " << i << std::endl;
}
@@ -331,24 +331,6 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
continue;
}
- // If the module is provided in this target special handling is
- // needed.
- if (this->Internal->TargetProvides.find(i) !=
- this->Internal->TargetProvides.end()) {
- // The module is provided by a different source in the same
- // target. Add the proxy dependency to make sure the other
- // source builds first.
- std::string proxy = stamp_dir;
- proxy += "/";
- proxy += i;
- proxy += ".mod.proxy";
- proxy = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, proxy).c_str());
-
- // since we require some things add them to our list of requirements
- makeDepends << obj_m << ".requires: " << proxy << std::endl;
- }
-
// The object file should depend on timestamped files for the
// modules it uses.
TargetRequiresMap::const_iterator required =
@@ -359,7 +341,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
if (!required->second.empty()) {
// This module is known. Depend on its timestamp file.
std::string stampFile = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, required->second).c_str());
+ this->MaybeConvertToRelativePath(binDir, required->second));
makeDepends << obj_m << ": " << stampFile << "\n";
} else {
// This module is not known to CMake. Try to locate it where
@@ -367,28 +349,16 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
std::string module;
if (this->FindModule(i, module)) {
module = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, module).c_str());
+ this->MaybeConvertToRelativePath(binDir, module));
makeDepends << obj_m << ": " << module << "\n";
}
}
}
- // Write provided modules to the output stream.
- for (std::string const& i : info.Provides) {
- std::string proxy = stamp_dir;
- proxy += "/";
- proxy += i;
- proxy += ".mod.proxy";
- proxy = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, proxy).c_str());
- makeDepends << proxy << ": " << obj_m << ".provides" << std::endl;
- }
-
// If any modules are provided then they must be converted to stamp files.
if (!info.Provides.empty()) {
// Create a target to copy the module after the object file
// changes.
- makeDepends << obj_m << ".provides.build:\n";
for (std::string const& i : info.Provides) {
// Include this module in the set provided by this target.
this->Internal->TargetProvides.insert(i);
@@ -407,11 +377,25 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
stampFile += "/";
stampFile += m;
stampFile += ".mod.stamp";
- stampFile = this->LocalGenerator->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(binDir, stampFile),
- cmOutputConverter::SHELL);
+ stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
+ std::string const stampFileForShell =
+ this->LocalGenerator->ConvertToOutputFormat(stampFile,
+ cmOutputConverter::SHELL);
+ std::string const stampFileForMake =
+ cmSystemTools::ConvertToOutputPath(stampFile);
+
+ makeDepends << obj_m << ".provides.build"
+ << ": " << stampFileForMake << "\n";
+ // Note that when cmake_copy_f90_mod finds that a module file
+ // and the corresponding stamp file have no differences, the stamp
+ // file is not updated. In such case the stamp file will be always
+ // older than its prerequisite and trigger cmake_copy_f90_mod
+ // on each new build. This is expected behavior for incremental
+ // builds and can not be changed without preforming recursive make
+ // calls that would considerably slow down the building process.
+ makeDepends << stampFileForMake << ": " << obj_m << "\n";
makeDepends << "\t$(CMAKE_COMMAND) -E cmake_copy_f90_mod " << modFile
- << " " << stampFile;
+ << " " << stampFileForShell;
cmMakefile* mf = this->LocalGenerator->GetMakefile();
const char* cid = mf->GetDefinition("CMAKE_Fortran_COMPILER_ID");
if (cid && *cid) {
@@ -419,8 +403,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
}
makeDepends << "\n";
}
- // After copying the modules update the timestamp file so that
- // copying will not be done again until the source rebuilds.
+ makeDepends << obj_m << ".provides.build:\n";
+ // After copying the modules update the timestamp file.
makeDepends << "\t$(CMAKE_COMMAND) -E touch " << obj_m
<< ".provides.build\n";
@@ -429,7 +413,7 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj,
std::string driver = this->TargetDirectory;
driver += "/build";
driver = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, driver).c_str());
+ this->MaybeConvertToRelativePath(binDir, driver));
makeDepends << driver << ": " << obj_m << ".provides.build\n";
}
@@ -451,7 +435,7 @@ bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
fullName = ip;
fullName += "/";
fullName += mod_lower;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ if (cmSystemTools::FileExists(fullName, true)) {
module = fullName;
return true;
}
@@ -460,7 +444,7 @@ bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
fullName = ip;
fullName += "/";
fullName += mod_upper;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ if (cmSystemTools::FileExists(fullName, true)) {
module = fullName;
return true;
}
@@ -497,7 +481,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
mod += ".mod";
mod_upper += ".mod";
mod_lower += ".mod";
- if (cmSystemTools::FileExists(mod_upper.c_str(), true)) {
+ if (cmSystemTools::FileExists(mod_upper, true)) {
if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(),
compilerId.c_str())) {
if (!cmSystemTools::CopyFileAlways(mod_upper, stamp)) {
@@ -508,7 +492,7 @@ bool cmDependsFortran::CopyModule(const std::vector<std::string>& args)
}
return true;
}
- if (cmSystemTools::FileExists(mod_lower.c_str(), true)) {
+ if (cmSystemTools::FileExists(mod_lower, true)) {
if (cmDependsFortran::ModulesDiffer(mod_lower.c_str(), stamp.c_str(),
compilerId.c_str())) {
if (!cmSystemTools::CopyFileAlways(mod_lower, stamp)) {
@@ -599,7 +583,7 @@ bool cmDependsFortran::ModulesDiffer(const char* modFile,
A mod file is a binary file.
However, looking into both generated bar.mod files with a hex editor
shows that they differ only before a sequence linefeed-zero (0x0A 0x00)
- which is located some bytes in front of the absoulte path to the source
+ which is located some bytes in front of the absolute path to the source
file.
sun:
diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h
index ccf267b2f..bee980471 100644
--- a/Source/cmDependsFortran.h
+++ b/Source/cmDependsFortran.h
@@ -64,7 +64,7 @@ protected:
const std::string& file, std::ostream& makeDepends,
std::ostream& internalDepends) override;
- // Actually write the depenencies to the streams.
+ // Actually write the dependencies to the streams.
bool WriteDependenciesReal(const char* obj, cmFortranSourceInfo const& info,
std::string const& mod_dir, const char* stamp_dir,
std::ostream& makeDepends,
diff --git a/Source/cmDependsJavaParserHelper.cxx b/Source/cmDependsJavaParserHelper.cxx
index f227cf25b..02db11978 100644
--- a/Source/cmDependsJavaParserHelper.cxx
+++ b/Source/cmDependsJavaParserHelper.cxx
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <utility>
int cmDependsJava_yyparse(yyscan_t yyscanner);
@@ -22,7 +23,7 @@ cmDependsJavaParserHelper::cmDependsJavaParserHelper()
CurrentClass tl;
tl.Name = "*";
- this->ClassStack.push_back(tl);
+ this->ClassStack.push_back(std::move(tl));
}
cmDependsJavaParserHelper::~cmDependsJavaParserHelper()
@@ -175,7 +176,7 @@ void cmDependsJavaParserHelper::StartClass(const char* cls)
{
CurrentClass cl;
cl.Name = cls;
- this->ClassStack.push_back(cl);
+ this->ClassStack.push_back(std::move(cl));
this->CurrentDepth++;
}
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index 0c9686087..2dfba04a7 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -213,7 +213,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
if (argc == 1) {
RequestedHelpItem help;
help.HelpType = cmDocumentation::Usage;
- this->RequestedHelpItems.push_back(help);
+ this->RequestedHelpItems.push_back(std::move(help));
return true;
}
@@ -352,7 +352,7 @@ bool cmDocumentation::CheckOptions(int argc, const char* const* argv,
if (help.HelpType != None) {
// This is a help option. See if there is a file name given.
result = true;
- this->RequestedHelpItems.push_back(help);
+ this->RequestedHelpItems.push_back(std::move(help));
}
}
return result;
diff --git a/Source/cmDocumentationSection.cxx b/Source/cmDocumentationSection.cxx
index c47f33e4f..439da1bc1 100644
--- a/Source/cmDocumentationSection.cxx
+++ b/Source/cmDocumentationSection.cxx
@@ -6,7 +6,7 @@ void cmDocumentationSection::Append(const char* data[][2])
{
int i = 0;
while (data[i][1]) {
- this->Entries.push_back(cmDocumentationEntry(data[i][0], data[i][1]));
+ this->Entries.emplace_back(data[i][0], data[i][1]);
data += 1;
}
}
@@ -16,7 +16,7 @@ void cmDocumentationSection::Prepend(const char* data[][2])
std::vector<cmDocumentationEntry> tmp;
int i = 0;
while (data[i][1]) {
- tmp.push_back(cmDocumentationEntry(data[i][0], data[i][1]));
+ tmp.emplace_back(data[i][0], data[i][1]);
data += 1;
}
this->Entries.insert(this->Entries.begin(), tmp.begin(), tmp.end());
@@ -24,5 +24,5 @@ void cmDocumentationSection::Prepend(const char* data[][2])
void cmDocumentationSection::Append(const char* n, const char* b)
{
- this->Entries.push_back(cmDocumentationEntry(n, b));
+ this->Entries.emplace_back(n, b);
}
diff --git a/Source/cmDuration.cxx b/Source/cmDuration.cxx
new file mode 100644
index 000000000..8ca5d8d12
--- /dev/null
+++ b/Source/cmDuration.cxx
@@ -0,0 +1,27 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#define CMDURATION_CPP
+#include "cmDuration.h"
+
+template <typename T>
+T cmDurationTo(const cmDuration& duration)
+{
+ /* This works because the comparison operators for duration rely on
+ * std::common_type.
+ * So for example duration<int>::max() gets promoted to a duration<double>,
+ * which can then be safely compared.
+ */
+ if (duration >= std::chrono::duration<T>::max()) {
+ return std::chrono::duration<T>::max().count();
+ }
+ if (duration <= std::chrono::duration<T>::min()) {
+ return std::chrono::duration<T>::min().count();
+ }
+ // Ensure number of seconds by defining ratio<1>
+ return std::chrono::duration_cast<std::chrono::duration<T, std::ratio<1>>>(
+ duration)
+ .count();
+}
+
+template int cmDurationTo<int>(const cmDuration&);
+template unsigned int cmDurationTo<unsigned int>(const cmDuration&);
diff --git a/Source/cmDuration.h b/Source/cmDuration.h
new file mode 100644
index 000000000..6df1455b4
--- /dev/null
+++ b/Source/cmDuration.h
@@ -0,0 +1,24 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+
+#include <chrono>
+#include <ratio>
+
+typedef std::chrono::duration<double, std::ratio<1>> cmDuration;
+
+/*
+ * This function will return number of seconds in the requested type T.
+ *
+ * A duration_cast from duration<double> to duration<T> will not yield what
+ * one might expect if the double representation does not fit into type T.
+ * This function aims to safely convert, by clamping the double value between
+ * the permissible valid values for T.
+ */
+template <typename T>
+T cmDurationTo(const cmDuration& duration);
+
+#ifndef CMDURATION_CPP
+extern template int cmDurationTo<int>(const cmDuration&);
+extern template unsigned int cmDurationTo<unsigned int>(const cmDuration&);
+#endif
diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx
index 76374b2f5..77ccd3096 100644
--- a/Source/cmELF.cxx
+++ b/Source/cmELF.cxx
@@ -547,8 +547,7 @@ cmELF::DynamicEntryList cmELFInternalImpl<Types>::GetDynamicEntries()
// Copy into public array
result.reserve(this->DynamicSectionEntries.size());
for (ELF_Dyn& dyn : this->DynamicSectionEntries) {
- result.push_back(
- std::pair<unsigned long, unsigned long>(dyn.d_tag, dyn.d_un.d_val));
+ result.emplace_back(dyn.d_tag, dyn.d_un.d_val);
}
return result;
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 88e085d5d..49f880c87 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -81,7 +81,7 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args,
std::string output;
bool result = true;
if (args.size() - count == 2) {
- cmSystemTools::MakeDirectory(args[1].c_str());
+ cmSystemTools::MakeDirectory(args[1]);
result = cmExecProgramCommand::RunCommand(command.c_str(), output, retVal,
args[1].c_str(), verbose);
} else {
@@ -149,7 +149,7 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output,
if (quoted.find(command)) {
std::string cmd = quoted.match(1);
std::string args = quoted.match(2);
- if (!cmSystemTools::FileExists(cmd.c_str())) {
+ if (!cmSystemTools::FileExists(cmd)) {
shortCmd = cmd;
} else if (!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd)) {
cmSystemTools::Error("GetShortPath failed for ", cmd.c_str());
diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx
index 39e774e83..679a64814 100644
--- a/Source/cmExecuteProcessCommand.cxx
+++ b/Source/cmExecuteProcessCommand.cxx
@@ -157,7 +157,7 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args,
}
}
- if (!this->Makefile->CanIWriteThisFile(output_file.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(output_file)) {
std::string e = "attempted to output into a file: " + output_file +
" into a source directory.";
this->SetError(e);
diff --git a/Source/cmExpandedCommandArgument.cxx b/Source/cmExpandedCommandArgument.cxx
index 0bea65fd0..1c0a72175 100644
--- a/Source/cmExpandedCommandArgument.cxx
+++ b/Source/cmExpandedCommandArgument.cxx
@@ -24,6 +24,11 @@ bool cmExpandedCommandArgument::WasQuoted() const
return this->Quoted;
}
+bool cmExpandedCommandArgument::operator==(const char* value) const
+{
+ return this->Value == value;
+}
+
bool cmExpandedCommandArgument::operator==(std::string const& value) const
{
return this->Value == value;
diff --git a/Source/cmExpandedCommandArgument.h b/Source/cmExpandedCommandArgument.h
index fe86528db..302e8dbd6 100644
--- a/Source/cmExpandedCommandArgument.h
+++ b/Source/cmExpandedCommandArgument.h
@@ -24,6 +24,7 @@ public:
bool WasQuoted() const;
+ bool operator==(const char* value) const;
bool operator==(std::string const& value) const;
bool empty() const;
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 5e2cd535d..817b5d9eb 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -8,6 +8,7 @@
#include <utility>
#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorTarget.h"
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
@@ -48,8 +49,7 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
os << "LOCAL_MODULE := ";
os << targetName << "\n";
os << "LOCAL_SRC_FILES := ";
- std::string path =
- cmSystemTools::ConvertToOutputPath(target->GetFullPath().c_str());
+ std::string path = cmSystemTools::ConvertToOutputPath(target->GetFullPath());
os << path << "\n";
}
@@ -102,12 +102,21 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
os << "LOCAL_CPP_FEATURES += ";
os << (property.second) << "\n";
} else if (property.first == "INTERFACE_LINK_LIBRARIES") {
+ // evaluate any generator expressions with the current
+ // build type of the makefile
+ cmGeneratorExpression ge;
+ cmGeneratorExpressionDAGChecker dagChecker(
+ target->GetName(), "INTERFACE_LINK_LIBRARIES", nullptr, nullptr);
+ std::unique_ptr<cmCompiledGeneratorExpression> cge =
+ ge.Parse(property.second);
+ std::string evaluated = cge->Evaluate(
+ target->GetLocalGenerator(), config, false, target, &dagChecker);
// need to look at list in pi->second and see if static or shared
// FindTargetToLink
// target->GetLocalGenerator()->FindGeneratorTargetToUse()
// then add to LOCAL_CPPFLAGS
std::vector<std::string> libraries;
- cmSystemTools::ExpandListArgument(property.second, libraries);
+ cmSystemTools::ExpandListArgument(evaluated, libraries);
std::string staticLibs;
std::string sharedLibs;
std::string ldlibs;
@@ -123,12 +132,6 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
staticLibs += " " + lib;
}
} else {
- // evaluate any generator expressions with the current
- // build type of the makefile
- cmGeneratorExpression ge;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(lib);
- std::string evaluated =
- cge->Evaluate(target->GetLocalGenerator(), config);
bool relpath = false;
if (type == cmExportBuildAndroidMKGenerator::INSTALL) {
relpath = lib.substr(0, 3) == "../";
@@ -136,12 +139,12 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties(
// check for full path or if it already has a -l, or
// in the case of an install check for relative paths
// if it is full or a link library then use string directly
- if (cmSystemTools::FileIsFullPath(evaluated) ||
- evaluated.substr(0, 2) == "-l" || relpath) {
- ldlibs += " " + evaluated;
+ if (cmSystemTools::FileIsFullPath(lib) ||
+ lib.substr(0, 2) == "-l" || relpath) {
+ ldlibs += " " + lib;
// if it is not a path and does not have a -l then add -l
- } else if (!evaluated.empty()) {
- ldlibs += " -l" + evaluated;
+ } else if (!lib.empty()) {
+ ldlibs += " -l" + lib;
}
}
}
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index bb1dda329..f7aa6e86f 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -228,7 +228,7 @@ void cmExportBuildFileGenerator::HandleMissingTarget(
missingTarget += dependee->GetExportName();
link_libs += missingTarget;
- missingTargets.push_back(missingTarget);
+ missingTargets.push_back(std::move(missingTarget));
return;
}
// We are not appending, so all exported targets should be
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 991312983..c8a727d70 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -92,8 +92,8 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
}
// Get the file to write.
- if (cmSystemTools::FileIsFullPath(fname.c_str())) {
- if (!this->Makefile->CanIWriteThisFile(fname.c_str())) {
+ if (cmSystemTools::FileIsFullPath(fname)) {
+ if (!this->Makefile->CanIWriteThisFile(fname)) {
std::ostringstream e;
e << "FILE option given filename \"" << fname
<< "\" which is in the source tree.\n";
@@ -205,7 +205,7 @@ bool cmExportCommand::InitialPass(std::vector<std::string> const& args,
std::vector<std::string> configurationTypes;
this->Makefile->GetConfigurations(configurationTypes);
if (configurationTypes.empty()) {
- configurationTypes.push_back("");
+ configurationTypes.emplace_back();
}
for (std::string const& ct : configurationTypes) {
ebfg->AddConfiguration(ct);
@@ -346,10 +346,10 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
fname += "/.cmake/packages/";
fname += package;
#endif
- cmSystemTools::MakeDirectory(fname.c_str());
+ cmSystemTools::MakeDirectory(fname);
fname += "/";
fname += hash;
- if (!cmSystemTools::FileExists(fname.c_str())) {
+ if (!cmSystemTools::FileExists(fname)) {
cmGeneratedFileStream entry(fname.c_str(), true);
if (entry) {
entry << content << "\n";
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 7f0cb9729..434abdc76 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -183,7 +183,7 @@ bool cmExportFileGenerator::PopulateInterfaceLinkLibrariesProperty(
return false;
}
-static bool isSubDirectory(const char* a, const char* b)
+static bool isSubDirectory(std::string const& a, std::string const& b)
{
return (cmSystemTools::ComparePath(a, b) ||
cmSystemTools::IsSubDirectory(a, b));
@@ -195,13 +195,15 @@ static bool checkInterfaceDirs(const std::string& prepro,
{
const char* installDir =
target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
- const char* topSourceDir = target->GetLocalGenerator()->GetSourceDirectory();
- const char* topBinaryDir = target->GetLocalGenerator()->GetBinaryDirectory();
+ std::string const& topSourceDir =
+ target->GetLocalGenerator()->GetSourceDirectory();
+ std::string const& topBinaryDir =
+ target->GetLocalGenerator()->GetBinaryDirectory();
std::vector<std::string> parts;
cmGeneratorExpression::Split(prepro, parts);
- const bool inSourceBuild = strcmp(topSourceDir, topBinaryDir) == 0;
+ const bool inSourceBuild = topSourceDir == topBinaryDir;
bool hadFatalError = false;
@@ -231,10 +233,10 @@ static bool checkInterfaceDirs(const std::string& prepro,
hadFatalError = true;
}
}
- if (cmHasLiteralPrefix(li.c_str(), "${_IMPORT_PREFIX}")) {
+ if (cmHasLiteralPrefix(li, "${_IMPORT_PREFIX}")) {
continue;
}
- if (!cmSystemTools::FileIsFullPath(li.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(li)) {
/* clang-format off */
e << "Target \"" << target->GetName() << "\" " << prop <<
" property contains relative path:\n"
@@ -242,9 +244,9 @@ static bool checkInterfaceDirs(const std::string& prepro,
/* clang-format on */
target->GetLocalGenerator()->IssueMessage(messageType, e.str());
}
- bool inBinary = isSubDirectory(li.c_str(), topBinaryDir);
- bool inSource = isSubDirectory(li.c_str(), topSourceDir);
- if (isSubDirectory(li.c_str(), installDir)) {
+ bool inBinary = isSubDirectory(li, topBinaryDir);
+ bool inSource = isSubDirectory(li, topSourceDir);
+ if (isSubDirectory(li, installDir)) {
// The include directory is inside the install tree. If the
// install tree is not inside the source tree or build tree then
// fall through to the checks below that the include directory is not
@@ -317,7 +319,7 @@ static void prefixItems(std::string& exportDirs)
for (std::string const& e : entries) {
exportDirs += sep;
sep = ";";
- if (!cmSystemTools::FileIsFullPath(e.c_str()) &&
+ if (!cmSystemTools::FileIsFullPath(e) &&
e.find("${_IMPORT_PREFIX}") == std::string::npos) {
exportDirs += "${_IMPORT_PREFIX}/";
}
@@ -591,7 +593,7 @@ void cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
std::string::size_type commaPos = input.find(',', nameStartPos);
std::string::size_type nextOpenPos = input.find("$<", nameStartPos);
if (commaPos == std::string::npos // Implied 'this' target
- || closePos == std::string::npos // Imcomplete expression.
+ || closePos == std::string::npos // Incomplete expression.
|| closePos < commaPos // Implied 'this' target
|| nextOpenPos < commaPos) // Non-literal
{
diff --git a/Source/cmExportInstallAndroidMKGenerator.h b/Source/cmExportInstallAndroidMKGenerator.h
index 316598290..91554ee30 100644
--- a/Source/cmExportInstallAndroidMKGenerator.h
+++ b/Source/cmExportInstallAndroidMKGenerator.h
@@ -22,7 +22,7 @@ class cmInstallExportGenerator;
* cmExportInstallAndroidMKGenerator generates files exporting targets from
* install an installation tree. The files are placed in a temporary
* location for installation by cmInstallExportGenerator. The file format
- * is for the ndk build system and is a makefile fragment specifing prebuilt
+ * is for the ndk build system and is a makefile fragment specifying prebuilt
* libraries to the ndk build system.
*
* This is used to implement the INSTALL(EXPORT_ANDROID_MK) command.
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 9b65e9e5c..954b5610b 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -185,12 +185,12 @@ void cmExportInstallFileGenerator::GenerateImportPrefix(std::ostream& os)
os << "# Compute the installation prefix relative to this file.\n"
<< "get_filename_component(_IMPORT_PREFIX"
<< " \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
- if (cmHasLiteralPrefix(absDestS.c_str(), "/lib/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/lib64/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/libx32/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/usr/lib64/") ||
- cmHasLiteralPrefix(absDestS.c_str(), "/usr/libx32/")) {
+ if (cmHasLiteralPrefix(absDestS, "/lib/") ||
+ cmHasLiteralPrefix(absDestS, "/lib64/") ||
+ cmHasLiteralPrefix(absDestS, "/libx32/") ||
+ cmHasLiteralPrefix(absDestS, "/usr/lib/") ||
+ cmHasLiteralPrefix(absDestS, "/usr/lib64/") ||
+ cmHasLiteralPrefix(absDestS, "/usr/libx32/")) {
// Handle "/usr move" symlinks created by some Linux distros.
/* clang-format off */
os <<
@@ -370,7 +370,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
// Construct the installed location of the target.
std::string dest = itgen->GetDestination(config);
std::string value;
- if (!cmSystemTools::FileIsFullPath(dest.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(dest)) {
// The target is installed relative to the installation prefix.
value = "${_IMPORT_PREFIX}/";
}
@@ -439,7 +439,7 @@ void cmExportInstallFileGenerator::HandleMissingTarget(
missingTarget += dependee->GetExportName();
link_libs += missingTarget;
- missingTargets.push_back(missingTarget);
+ missingTargets.push_back(std::move(missingTarget));
} else {
// All exported targets should be known here and should be unique.
// This is probably user-error.
diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx
index 1fb9cf818..ae8cd3743 100644
--- a/Source/cmExportTryCompileFileGenerator.cxx
+++ b/Source/cmExportTryCompileFileGenerator.cxx
@@ -18,7 +18,8 @@
cmExportTryCompileFileGenerator::cmExportTryCompileFileGenerator(
cmGlobalGenerator* gg, const std::vector<std::string>& targets,
- cmMakefile* mf)
+ cmMakefile* mf, std::set<std::string> const& langs)
+ : Languages(langs.begin(), langs.end())
{
gg->CreateImportedGenerationObjects(mf, targets, this->Exports);
}
@@ -36,12 +37,14 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
ImportPropertyMap properties;
+ for (std::string const& lang : this->Languages) {
#define FIND_TARGETS(PROPERTY) \
- this->FindTargets("INTERFACE_" #PROPERTY, te, emittedDeps);
+ this->FindTargets("INTERFACE_" #PROPERTY, te, lang, emittedDeps);
- CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(FIND_TARGETS)
#undef FIND_TARGETS
+ }
this->PopulateProperties(te, properties, emittedDeps);
@@ -53,7 +56,7 @@ bool cmExportTryCompileFileGenerator::GenerateMainFile(std::ostream& os)
std::string cmExportTryCompileFileGenerator::FindTargets(
const std::string& propName, cmGeneratorTarget const* tgt,
- std::set<cmGeneratorTarget const*>& emitted)
+ std::string const& language, std::set<cmGeneratorTarget const*>& emitted)
{
const char* prop = tgt->GetProperty(propName);
if (!prop) {
@@ -72,8 +75,9 @@ std::string cmExportTryCompileFileGenerator::FindTargets(
cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator());
- std::string result = cge->Evaluate(tgt->GetLocalGenerator(), this->Config,
- false, &gDummyHead, tgt, &dagChecker);
+ std::string result =
+ cge->Evaluate(tgt->GetLocalGenerator(), this->Config, false, &gDummyHead,
+ tgt, &dagChecker, language);
const std::set<cmGeneratorTarget const*>& allTargets =
cge->GetAllTargetsSeen();
@@ -97,7 +101,8 @@ void cmExportTryCompileFileGenerator::PopulateProperties(
if (p.find("IMPORTED_LINK_INTERFACE_LIBRARIES") == 0 ||
p.find("IMPORTED_LINK_DEPENDENT_LIBRARIES") == 0 ||
p.find("INTERFACE_LINK_LIBRARIES") == 0) {
- std::string evalResult = this->FindTargets(p, target, emitted);
+ std::string evalResult =
+ this->FindTargets(p, target, std::string(), emitted);
std::vector<std::string> depends;
cmSystemTools::ExpandListArgument(evalResult, depends);
diff --git a/Source/cmExportTryCompileFileGenerator.h b/Source/cmExportTryCompileFileGenerator.h
index 70c385728..ca2987caf 100644
--- a/Source/cmExportTryCompileFileGenerator.h
+++ b/Source/cmExportTryCompileFileGenerator.h
@@ -21,7 +21,8 @@ class cmExportTryCompileFileGenerator : public cmExportFileGenerator
public:
cmExportTryCompileFileGenerator(cmGlobalGenerator* gg,
std::vector<std::string> const& targets,
- cmMakefile* mf);
+ cmMakefile* mf,
+ std::set<std::string> const& langs);
/** Set the list of targets to export. */
void SetConfig(const std::string& config) { this->Config = config; }
@@ -49,10 +50,12 @@ protected:
private:
std::string FindTargets(const std::string& prop,
const cmGeneratorTarget* tgt,
+ std::string const& language,
std::set<const cmGeneratorTarget*>& emitted);
std::vector<cmGeneratorTarget const*> Exports;
std::string Config;
+ std::vector<std::string> Languages;
};
#endif
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index 825ec654e..fecd8216e 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -24,6 +24,13 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
return fullName;
}
+bool cmExternalMakefileProjectGenerator::Open(
+ const std::string& /*bindir*/, const std::string& /*projectName*/,
+ bool /*dryRun*/)
+{
+ return false;
+}
+
cmExternalMakefileProjectGeneratorFactory::
cmExternalMakefileProjectGeneratorFactory(const std::string& n,
const std::string& doc)
diff --git a/Source/cmExternalMakefileProjectGenerator.h b/Source/cmExternalMakefileProjectGenerator.h
index a1734eef2..5cc6442e7 100644
--- a/Source/cmExternalMakefileProjectGenerator.h
+++ b/Source/cmExternalMakefileProjectGenerator.h
@@ -17,7 +17,7 @@ class cmMakefile;
* cmExternalMakefileProjectGenerator is a base class for generators
* for "external makefile based projects", i.e. IDE projects which work
* an already existing makefiles.
- * See cmGlobalKdevelopGenerator as an example.
+ * See cmExtraEclipseCDT4Generator as an example.
* After the makefiles have been generated by one of the Makefile
* generators, the Generate() method is called and this generator
* can iterate over the local generators and/or projects to produce the
@@ -55,6 +55,9 @@ public:
void SetName(const std::string& n) { Name = n; }
std::string GetName() const { return Name; }
+ virtual bool Open(const std::string& bindir, const std::string& projectName,
+ bool dryRun);
+
protected:
///! Contains the names of the global generators support by this generator.
std::vector<std::string> SupportedGlobalGenerators;
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 9c9b75b17..4b95140ad 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -5,7 +5,6 @@
#include <map>
#include <ostream>
#include <set>
-#include <string.h>
#include <utility>
#include "cmAlgorithms.h"
@@ -225,7 +224,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
}
const std::string& relative = cmSystemTools::RelativePath(
- it.second[0]->GetSourceDirectory(), listFile.c_str());
+ it.second[0]->GetSourceDirectory(), listFile);
std::vector<std::string> splitted;
cmSystemTools::SplitPath(relative, splitted, false);
// Split filename from path
@@ -296,8 +295,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp(lg->GetCurrentBinaryDirectory(),
- lg->GetBinaryDirectory()) == 0) {
+ if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
this->AppendTarget(xml, targetName, nullptr, make.c_str(), lg,
compiler.c_str(), makeArgs);
}
@@ -345,8 +343,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();
@@ -372,28 +369,23 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
continue;
}
- // check whether it is a C/C++ implementation file
+ // check whether it is a C/C++/CUDA implementation file
bool isCFile = false;
std::string lang = s->GetLanguage();
- if (lang == "C" || lang == "CXX") {
+ if (lang == "C" || lang == "CXX" || lang == "CUDA") {
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();
// Check file position relative to project root dir.
- const std::string& relative = cmSystemTools::RelativePath(
- (*lg).GetSourceDirectory(), fullPath.c_str());
+ const std::string& relative =
+ cmSystemTools::RelativePath(lg->GetSourceDirectory(), fullPath);
// Do not add this file if it has ".." in relative path and
// if CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES variable is on.
const bool excludeExternal =
- cmSystemTools::IsOn((*lg).GetMakefile()->GetSafeDefinition(
+ cmSystemTools::IsOn(lg->GetMakefile()->GetSafeDefinition(
"CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES"));
if (excludeExternal &&
(relative.find("..") != std::string::npos)) {
@@ -422,7 +414,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
// C/C++ source files,
// replacing the file name extension with ".h" and checks whether such a
// file exists. If it does, it is inserted into the map of files.
- // A very similar version of that code exists also in the kdevelop
+ // A very similar version of that code exists also in the CodeLite
// project generator.
for (std::string const& fileName : cFiles) {
std::string headerBasename = cmSystemTools::GetFilenamePath(fileName);
@@ -439,7 +431,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
break;
}
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
allFiles[hname].Targets = allFiles[fileName].Targets;
break;
}
@@ -648,6 +640,13 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
// Translate the cmake compiler id into the CodeBlocks compiler id
std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
{
+ // allow the user to overwrite the detected compiler
+ std::string userCompiler =
+ mf->GetSafeDefinition("CMAKE_CODEBLOCKS_COMPILER_ID");
+ if (!userCompiler.empty()) {
+ return userCompiler;
+ }
+
// figure out which language to use
// for now care only for C, C++, and Fortran
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 5a02d54eb..4dbaa3f41 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -64,8 +64,8 @@ void cmExtraCodeLiteGenerator::Generate()
const cmMakefile* mf = it.second[0]->GetMakefile();
this->ConfigName = GetConfigurationName(mf);
- if (strcmp(it.second[0]->GetCurrentBinaryDirectory(),
- it.second[0]->GetBinaryDirectory()) == 0) {
+ if (it.second[0]->GetCurrentBinaryDirectory() ==
+ it.second[0]->GetBinaryDirectory()) {
workspaceOutputDir = it.second[0]->GetCurrentBinaryDirectory();
workspaceProjectName = it.second[0]->GetProjectName();
workspaceSourcePath = it.second[0]->GetSourceDirectory();
@@ -127,8 +127,8 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByTarget(
std::string filename = outputDir + "/" + targetName + ".project";
retval.push_back(targetName);
// Make the project file relative to the workspace
- std::string relafilename = cmSystemTools::RelativePath(
- this->WorkspacePath.c_str(), filename.c_str());
+ std::string relafilename =
+ cmSystemTools::RelativePath(this->WorkspacePath, filename);
std::string visualname = targetName;
switch (type) {
case cmStateEnums::SHARED_LIBRARY:
@@ -167,8 +167,7 @@ std::vector<std::string> cmExtraCodeLiteGenerator::CreateProjectsByProjectMaps(
std::string filename = outputDir + "/" + projectName + ".project";
// Make the project file relative to the workspace
- filename = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
- filename.c_str());
+ filename = cmSystemTools::RelativePath(this->WorkspacePath, filename);
// create a project file
this->CreateProjectFile(it.second);
@@ -198,9 +197,6 @@ 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();
-
std::string projectType;
switch (gt->GetType()) {
case cmStateEnums::EXECUTABLE: {
@@ -228,24 +224,18 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles(
gt->GetSourceFiles(sources,
makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
for (cmSourceFile* s : sources) {
- // check whether it is a C/C++ implementation file
- bool isCFile = false;
- 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;
- }
- }
- }
-
+ // check whether it is a source or a include file
// then put it accordingly into one of the two containers
- if (isCFile) {
- cFiles[s->GetFullPath()] = s;
- } else {
- otherFiles.insert(s->GetFullPath());
+ switch (cmSystemTools::GetFileFormat(s->GetExtension().c_str())) {
+ case cmSystemTools::C_FILE_FORMAT:
+ case cmSystemTools::CXX_FILE_FORMAT:
+ case cmSystemTools::CUDA_FILE_FORMAT:
+ case cmSystemTools::FORTRAN_FILE_FORMAT: {
+ cFiles[s->GetFullPath()] = s;
+ } break;
+ default: {
+ otherFiles.insert(s->GetFullPath());
+ }
}
}
}
@@ -309,7 +299,7 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
// files to the project. It does that by iterating over all source files,
// replacing the file name extension with ".h" and checks whether such a
// file exists. If it does, it is inserted into the map of files.
- // A very similar version of that code exists also in the kdevelop
+ // A very similar version of that code exists also in the CodeBlocks
// project generator.
for (auto const& sit : cFiles) {
std::string headerBasename = cmSystemTools::GetFilenamePath(sit.first);
@@ -327,7 +317,7 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
break;
}
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
otherFiles.insert(hname);
break;
}
@@ -344,8 +334,7 @@ void cmExtraCodeLiteGenerator::CreateFoldersAndFiles(
size_t numOfEndEl = 0;
for (std::string const& cFile : cFiles) {
- std::string frelapath =
- cmSystemTools::RelativePath(projectPath.c_str(), cFile.c_str());
+ std::string frelapath = cmSystemTools::RelativePath(projectPath, cFile);
cmsys::SystemTools::SplitPath(frelapath, components, false);
components.pop_back(); // erase last member -> it is file, not folder
components.erase(components.begin()); // erase "root"
@@ -483,8 +472,7 @@ void cmExtraCodeLiteGenerator::CreateProjectSourceEntries(
std::string outputPath = mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH");
std::string relapath;
if (!outputPath.empty()) {
- relapath = cmSystemTools::RelativePath(this->WorkspacePath.c_str(),
- outputPath.c_str());
+ relapath = cmSystemTools::RelativePath(this->WorkspacePath, outputPath);
xml.Attribute("OutputFile", relapath + "/$(ProjectName)");
} else {
xml.Attribute("OutputFile", "$(IntermediateDirectory)/$(ProjectName)");
@@ -685,7 +673,11 @@ std::string cmExtraCodeLiteGenerator::GetSingleFileBuildCommand(
std::string generator = mf->GetSafeDefinition("CMAKE_GENERATOR");
if (generator == "Unix Makefiles" || generator == "MinGW Makefiles") {
std::ostringstream ss;
- ss << make << " -f$(ProjectPath)/Makefile $(CurrentFileName).cpp.o";
+#if defined(_WIN32)
+ ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).obj";
+#else
+ ss << make << " -f$(ProjectPath)/Makefile -B $(CurrentFileFullName).o";
+#endif
buildCommand = ss.str();
}
return buildCommand;
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index a200385ee..258c9ca26 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -413,7 +413,7 @@ void cmExtraEclipseCDT4Generator::CreateProjectFile()
this->AppendLinkedResource(xml, sourceLinkedResourceName,
this->GetEclipsePath(linkSourceDirectory),
LinkToFolder);
- this->SrcLinkedResources.push_back(sourceLinkedResourceName);
+ this->SrcLinkedResources.push_back(std::move(sourceLinkedResourceName));
}
}
@@ -498,7 +498,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
// Add the file to the list of sources.
std::string const& source = sf->GetFullPath();
cmSourceGroup* sourceGroup =
- makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ makefile->FindSourceGroup(source, sourceGroups);
sourceGroup->AssignSource(sf);
}
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 79cc6ef52..7a83e4148 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -81,12 +81,12 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
const std::string makeArgs =
mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS");
- const char* homeOutputDir = lg->GetBinaryDirectory();
+ std::string const& homeOutputDir = lg->GetBinaryDirectory();
/* clang-format off */
fout <<
"\t\"build\": {\n"
- "\t\t\"directory\": \"" << lg->GetBinaryDirectory() << "\",\n"
+ "\t\t\"directory\": \"" << homeOutputDir << "\",\n"
"\t\t\"default_target\": \"all\",\n"
"\t\t\"clean_target\": \"clean\",\n";
/* clang-format on */
@@ -195,13 +195,13 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
const std::string& make,
const std::string& makeArgs,
const std::string& path,
- const char* homeOutputDir) const
+ const std::string& homeOutputDir) const
{
static char JsonSep = ' ';
fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target << "\", "
"\"build_cmd\":\""
- << make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path.c_str())
+ << make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path)
<< "\\\" " << makeArgs << " " << target << "\"}\n";
JsonSep = ',';
@@ -228,14 +228,14 @@ std::string cmExtraKateGenerator::GenerateFilesString(
{
std::string s = lg->GetSourceDirectory();
s += "/.git";
- if (cmSystemTools::FileExists(s.c_str())) {
- return std::string("\"git\": 1 ");
+ if (cmSystemTools::FileExists(s)) {
+ return "\"git\": 1 ";
}
s = lg->GetSourceDirectory();
s += "/.svn";
- if (cmSystemTools::FileExists(s.c_str())) {
- return std::string("\"svn\": 1 ");
+ if (cmSystemTools::FileExists(s)) {
+ return "\"svn\": 1 ";
}
s = lg->GetSourceDirectory();
diff --git a/Source/cmExtraKateGenerator.h b/Source/cmExtraKateGenerator.h
index 9716fe750..a4355f00c 100644
--- a/Source/cmExtraKateGenerator.h
+++ b/Source/cmExtraKateGenerator.h
@@ -31,7 +31,8 @@ private:
cmGeneratedFileStream& fout) const;
void AppendTarget(cmGeneratedFileStream& fout, const std::string& target,
const std::string& make, const std::string& makeArgs,
- const std::string& path, const char* homeOutputDir) const;
+ const std::string& path,
+ const std::string& homeOutputDir) const;
std::string GenerateFilesString(const cmLocalGenerator* lg) const;
std::string GetPathBasename(const std::string& path) const;
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 73a9c8521..46dcaf649 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -188,8 +188,7 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
case cmStateEnums::GLOBAL_TARGET: {
// Only add the global targets from CMAKE_BINARY_DIR,
// not from the subdirs
- if (strcmp(lg->GetCurrentBinaryDirectory(),
- lg->GetBinaryDirectory()) == 0) {
+ if (lg->GetCurrentBinaryDirectory() == lg->GetBinaryDirectory()) {
this->AppendTarget(fout, targetName, lg, nullptr, make.c_str(),
makefile, compiler.c_str(), sourceFileFlags,
false);
@@ -257,6 +256,8 @@ void cmExtraSublimeTextGenerator::AppendTarget(
std::string flagsString =
this->ComputeFlagsForObject(sourceFile, lg, target);
std::string definesString = this->ComputeDefines(sourceFile, lg, target);
+ std::string includesString =
+ this->ComputeIncludes(sourceFile, lg, target);
flags.clear();
cmsys::RegularExpression flagRegex;
// Regular expression to extract compiler flags from a string
@@ -264,7 +265,8 @@ void cmExtraSublimeTextGenerator::AppendTarget(
const char* regexString =
"(^|[ ])-[DIOUWfgs][^= ]+(=\\\"[^\"]+\\\"|=[^\"][^ ]+)?";
flagRegex.compile(regexString);
- std::string workString = flagsString + " " + definesString;
+ std::string workString =
+ flagsString + " " + definesString + " " + includesString;
while (flagRegex.find(workString)) {
std::string::size_type start = flagRegex.start();
if (workString[start] == ' ') {
@@ -351,20 +353,19 @@ std::string cmExtraSublimeTextGenerator::ComputeFlagsForObject(
lg->GetTargetCompileFlags(gtgt, config, language, flags);
- // Add include directory flags.
- {
- std::vector<std::string> includes;
- lg->GetIncludeDirectories(includes, gtgt, language, config);
- std::string includeFlags = lg->GetIncludeFlags(includes, gtgt, language,
- true); // full include paths
- lg->AppendFlags(flags, includeFlags);
+ // Add source file specific flags.
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, gtgt, config,
+ gtgt->GetName(), language);
+
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
+ lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
}
- // Add source file specific flags.
- if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- const char* processed = ge.Parse(cflags)->Evaluate(lg, config);
- lg->AppendFlags(flags, processed);
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
@@ -380,6 +381,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
cmMakefile* makefile = lg->GetMakefile();
const std::string& language = source->GetLanguage();
const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ lg, target, config, target->GetName(), language);
// Add the export symbol definition for shared library objects.
if (const char* exportMacro = target->GetExportMacro()) {
@@ -388,11 +391,17 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
// Add preprocessor definitions for this target and configuration.
lg->AddCompileDefinitions(defines, target, config, language);
- lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
- {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(config);
- lg->AppendDefines(defines, source->GetProperty(defPropName));
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
+ lg->AppendDefines(
+ defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS));
+ }
+
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(config);
+ if (const char* config_compile_defs = source->GetProperty(defPropName)) {
+ lg->AppendDefines(defines, genexInterpreter.Evaluate(config_compile_defs,
+ COMPILE_DEFINITIONS));
}
std::string definesString;
@@ -400,3 +409,54 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
return definesString;
}
+
+std::string cmExtraSublimeTextGenerator::ComputeIncludes(
+ cmSourceFile* source, cmLocalGenerator* lg, cmGeneratorTarget* target)
+
+{
+ std::vector<std::string> includes;
+ cmMakefile* makefile = lg->GetMakefile();
+ const std::string& language = source->GetLanguage();
+ const std::string& config = makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ lg, target, config, target->GetName(), language);
+
+ // Add include directories for this source file
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
+ lg->AppendIncludeDirectories(
+ includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
+ *source);
+ }
+
+ // Add include directory flags.
+ lg->GetIncludeDirectories(includes, target, language, config);
+
+ std::string includesString =
+ lg->GetIncludeFlags(includes, target, language, true, false, config);
+
+ return includesString;
+}
+
+bool cmExtraSublimeTextGenerator::Open(const std::string& bindir,
+ const std::string& projectName,
+ bool dryRun)
+{
+ const char* sublExecutable =
+ this->GlobalGenerator->GetCMakeInstance()->GetCacheDefinition(
+ "CMAKE_SUBLIMETEXT_EXECUTABLE");
+ if (!sublExecutable) {
+ return false;
+ }
+ if (cmSystemTools::IsNOTFOUND(sublExecutable)) {
+ return false;
+ }
+
+ std::string filename = bindir + "/" + projectName + ".sublime-project";
+ if (dryRun) {
+ return cmSystemTools::FileExists(filename, true);
+ }
+
+ return cmSystemTools::RunSingleCommand(
+ { sublExecutable, "--project", filename });
+}
diff --git a/Source/cmExtraSublimeTextGenerator.h b/Source/cmExtraSublimeTextGenerator.h
index 7fb304e11..bc158f6b4 100644
--- a/Source/cmExtraSublimeTextGenerator.h
+++ b/Source/cmExtraSublimeTextGenerator.h
@@ -65,6 +65,12 @@ private:
std::string ComputeDefines(cmSourceFile* source, cmLocalGenerator* lg,
cmGeneratorTarget* gtgt);
+ std::string ComputeIncludes(cmSourceFile* source, cmLocalGenerator* lg,
+ cmGeneratorTarget* gtgt);
+
+ bool Open(const std::string& bindir, const std::string& projectName,
+ bool dryRun) override;
+
bool ExcludeBuildFolder;
std::string EnvSettings;
};
diff --git a/Source/cmFSPermissions.cxx b/Source/cmFSPermissions.cxx
new file mode 100644
index 000000000..4015a5164
--- /dev/null
+++ b/Source/cmFSPermissions.cxx
@@ -0,0 +1,34 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#include "cmFSPermissions.h"
+
+bool cmFSPermissions::stringToModeT(std::string const& arg,
+ mode_t& permissions)
+{
+ if (arg == "OWNER_READ") {
+ permissions |= mode_owner_read;
+ } else if (arg == "OWNER_WRITE") {
+ permissions |= mode_owner_write;
+ } else if (arg == "OWNER_EXECUTE") {
+ permissions |= mode_owner_execute;
+ } else if (arg == "GROUP_READ") {
+ permissions |= mode_group_read;
+ } else if (arg == "GROUP_WRITE") {
+ permissions |= mode_group_write;
+ } else if (arg == "GROUP_EXECUTE") {
+ permissions |= mode_group_execute;
+ } else if (arg == "WORLD_READ") {
+ permissions |= mode_world_read;
+ } else if (arg == "WORLD_WRITE") {
+ permissions |= mode_world_write;
+ } else if (arg == "WORLD_EXECUTE") {
+ permissions |= mode_world_execute;
+ } else if (arg == "SETUID") {
+ permissions |= mode_setuid;
+ } else if (arg == "SETGID") {
+ permissions |= mode_setgid;
+ } else {
+ return false;
+ }
+ return true;
+}
diff --git a/Source/cmFSPermissions.h b/Source/cmFSPermissions.h
new file mode 100644
index 000000000..7a6e70866
--- /dev/null
+++ b/Source/cmFSPermissions.h
@@ -0,0 +1,45 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmFSPermissions_h
+#define cmFSPermissions_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_sys_stat.h"
+
+#include <string>
+
+namespace cmFSPermissions {
+
+// Table of permissions flags.
+#if defined(_WIN32) && !defined(__CYGWIN__)
+static const mode_t mode_owner_read = S_IREAD;
+static const mode_t mode_owner_write = S_IWRITE;
+static const mode_t mode_owner_execute = S_IEXEC;
+static const mode_t mode_group_read = 040;
+static const mode_t mode_group_write = 020;
+static const mode_t mode_group_execute = 010;
+static const mode_t mode_world_read = 04;
+static const mode_t mode_world_write = 02;
+static const mode_t mode_world_execute = 01;
+static const mode_t mode_setuid = 04000;
+static const mode_t mode_setgid = 02000;
+#else
+static const mode_t mode_owner_read = S_IRUSR;
+static const mode_t mode_owner_write = S_IWUSR;
+static const mode_t mode_owner_execute = S_IXUSR;
+static const mode_t mode_group_read = S_IRGRP;
+static const mode_t mode_group_write = S_IWGRP;
+static const mode_t mode_group_execute = S_IXGRP;
+static const mode_t mode_world_read = S_IROTH;
+static const mode_t mode_world_write = S_IWOTH;
+static const mode_t mode_world_execute = S_IXOTH;
+static const mode_t mode_setuid = S_ISUID;
+static const mode_t mode_setgid = S_ISGID;
+#endif
+
+bool stringToModeT(std::string const& arg, mode_t& permissions);
+
+} // ns
+
+#endif
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index fdd5f0c81..d3dcc0112 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -20,6 +20,7 @@
#include "cmAlgorithms.h"
#include "cmCommandArgumentsHelper.h"
#include "cmCryptoHash.h"
+#include "cmFSPermissions.h"
#include "cmFileLockPool.h"
#include "cmFileTimeComparison.h"
#include "cmGeneratorExpression.h"
@@ -50,32 +51,7 @@
class cmSystemToolsFileTime;
-// Table of permissions flags.
-#if defined(_WIN32) && !defined(__CYGWIN__)
-static mode_t mode_owner_read = S_IREAD;
-static mode_t mode_owner_write = S_IWRITE;
-static mode_t mode_owner_execute = S_IEXEC;
-static mode_t mode_group_read = 040;
-static mode_t mode_group_write = 020;
-static mode_t mode_group_execute = 010;
-static mode_t mode_world_read = 04;
-static mode_t mode_world_write = 02;
-static mode_t mode_world_execute = 01;
-static mode_t mode_setuid = 04000;
-static mode_t mode_setgid = 02000;
-#else
-static mode_t mode_owner_read = S_IRUSR;
-static mode_t mode_owner_write = S_IWUSR;
-static mode_t mode_owner_execute = S_IXUSR;
-static mode_t mode_group_read = S_IRGRP;
-static mode_t mode_group_write = S_IWGRP;
-static mode_t mode_group_execute = S_IXGRP;
-static mode_t mode_world_read = S_IROTH;
-static mode_t mode_world_write = S_IWOTH;
-static mode_t mode_world_execute = S_IXOTH;
-static mode_t mode_setuid = S_ISUID;
-static mode_t mode_setgid = S_ISGID;
-#endif
+using namespace cmFSPermissions;
#if defined(_WIN32)
// libcurl doesn't support file:// urls for unicode filenames on Windows.
@@ -207,14 +183,14 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
i++; // Get rid of subcommand
std::string fileName = *i;
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + *i;
}
i++;
- if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(fileName)) {
std::string e =
"attempted to write a file: " + fileName + " into a source directory.";
this->SetError(e);
@@ -222,7 +198,7 @@ bool cmFileCommand::HandleWriteCommand(std::vector<std::string> const& args,
return false;
}
std::string dir = cmSystemTools::GetFilenamePath(fileName);
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
@@ -282,7 +258,7 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
argHelper.Parse(&args, nullptr);
std::string fileName = fileNameArg.GetString();
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + fileNameArg.GetString();
}
@@ -398,7 +374,7 @@ bool cmFileCommand::HandleStringsCommand(std::vector<std::string> const& args)
// Get the file to read.
std::string fileName = args[1];
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + args[1];
}
@@ -824,7 +800,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
}
cmsys::Glob::GlobMessages globMessages;
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
std::string expr = this->Makefile->GetCurrentSourceDirectory();
// Handle script mode
if (!expr.empty()) {
@@ -908,19 +884,19 @@ bool cmFileCommand::HandleMakeDirectoryCommand(
std::string expr;
for (; i != args.end(); ++i) {
const std::string* cdir = &(*i);
- if (!cmsys::SystemTools::FileIsFullPath(i->c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(*i)) {
expr = this->Makefile->GetCurrentSourceDirectory();
expr += "/" + *i;
cdir = &expr;
}
- if (!this->Makefile->CanIWriteThisFile(cdir->c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(*cdir)) {
std::string e = "attempted to create a directory: " + *cdir +
" into a source directory.";
this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
- if (!cmSystemTools::MakeDirectory(cdir->c_str())) {
+ if (!cmSystemTools::MakeDirectory(*cdir)) {
std::string error = "problem creating directory: " + *cdir;
this->SetError(error);
return false;
@@ -1099,29 +1075,7 @@ protected:
// Translate an argument to a permissions bit.
bool CheckPermissions(std::string const& arg, mode_t& permissions)
{
- if (arg == "OWNER_READ") {
- permissions |= mode_owner_read;
- } else if (arg == "OWNER_WRITE") {
- permissions |= mode_owner_write;
- } else if (arg == "OWNER_EXECUTE") {
- permissions |= mode_owner_execute;
- } else if (arg == "GROUP_READ") {
- permissions |= mode_group_read;
- } else if (arg == "GROUP_WRITE") {
- permissions |= mode_group_write;
- } else if (arg == "GROUP_EXECUTE") {
- permissions |= mode_group_execute;
- } else if (arg == "WORLD_READ") {
- permissions |= mode_world_read;
- } else if (arg == "WORLD_WRITE") {
- permissions |= mode_world_write;
- } else if (arg == "WORLD_EXECUTE") {
- permissions |= mode_world_execute;
- } else if (arg == "SETUID") {
- permissions |= mode_setuid;
- } else if (arg == "SETGID") {
- permissions |= mode_setgid;
- } else {
+ if (!cmFSPermissions::stringToModeT(arg, permissions)) {
std::ostringstream e;
e << this->Name << " given invalid permission \"" << arg << "\".";
this->FileCommand->SetError(e.str());
@@ -1340,7 +1294,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
this->Files.push_back(arg);
break;
case DoingDestination:
- if (arg.empty() || cmSystemTools::FileIsFullPath(arg.c_str())) {
+ if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) {
this->Destination = arg;
} else {
this->Destination = this->Makefile->GetCurrentBinaryDirectory();
@@ -1349,7 +1303,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
this->Doing = DoingNone;
break;
case DoingFilesFromDir:
- if (cmSystemTools::FileIsFullPath(arg.c_str())) {
+ if (cmSystemTools::FileIsFullPath(arg)) {
this->FilesFromDir = arg;
} else {
this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
@@ -1366,7 +1320,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
std::string regex = "/";
regex += cmsys::Glob::PatternToRegex(arg, false);
regex += "$";
- this->MatchRules.push_back(MatchRule(regex));
+ this->MatchRules.emplace_back(regex);
this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
if (this->CurrentMatchRule->Regex.is_valid()) {
this->Doing = DoingNone;
@@ -1378,7 +1332,7 @@ bool cmFileCopier::CheckValue(std::string const& arg)
}
} break;
case DoingRegex:
- this->MatchRules.push_back(MatchRule(arg));
+ this->MatchRules.emplace_back(arg);
this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
if (this->CurrentMatchRule->Regex.is_valid()) {
this->Doing = DoingNone;
@@ -2015,9 +1969,30 @@ bool cmFileInstaller::HandleInstallDestination()
this->DestDirLength = int(sdestdir.size());
}
+ // check if default dir creation permissions were set
+ mode_t default_dir_mode_v = 0;
+ mode_t* default_dir_mode = nullptr;
+ const char* default_dir_install_permissions = this->Makefile->GetDefinition(
+ "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS");
+ if (default_dir_install_permissions && *default_dir_install_permissions) {
+ std::vector<std::string> items;
+ cmSystemTools::ExpandListArgument(default_dir_install_permissions, items);
+ for (const auto& arg : items) {
+ if (!this->CheckPermissions(arg, default_dir_mode_v)) {
+ std::ostringstream e;
+ e << this->FileCommand->GetError()
+ << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable.";
+ this->FileCommand->SetError(e.str());
+ return false;
+ }
+ }
+
+ default_dir_mode = &default_dir_mode_v;
+ }
+
if (this->InstallType != cmInstallType_DIRECTORY) {
- if (!cmSystemTools::FileExists(destination.c_str())) {
- if (!cmSystemTools::MakeDirectory(destination.c_str())) {
+ if (!cmSystemTools::FileExists(destination)) {
+ if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) {
std::string errstring = "cannot create directory: " + destination +
". Maybe need administrative privileges.";
this->FileCommand->SetError(errstring);
@@ -2318,22 +2293,21 @@ bool cmFileCommand::HandleRelativePathCommand(
const std::string& directoryName = args[2];
const std::string& fileName = args[3];
- if (!cmSystemTools::FileIsFullPath(directoryName.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(directoryName)) {
std::string errstring =
"RELATIVE_PATH must be passed a full path to the directory: " +
directoryName;
this->SetError(errstring);
return false;
}
- if (!cmSystemTools::FileIsFullPath(fileName.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(fileName)) {
std::string errstring =
"RELATIVE_PATH must be passed a full path to the file: " + fileName;
this->SetError(errstring);
return false;
}
- std::string res =
- cmSystemTools::RelativePath(directoryName.c_str(), fileName.c_str());
+ std::string res = cmSystemTools::RelativePath(directoryName, fileName);
this->Makefile->AddDefinition(outVar, res.c_str());
return true;
}
@@ -2347,12 +2321,12 @@ bool cmFileCommand::HandleRename(std::vector<std::string> const& args)
// Compute full path for old and new names.
std::string oldname = args[1];
- if (!cmsys::SystemTools::FileIsFullPath(oldname.c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
oldname = this->Makefile->GetCurrentSourceDirectory();
oldname += "/" + args[1];
}
std::string newname = args[2];
- if (!cmsys::SystemTools::FileIsFullPath(newname.c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(newname)) {
newname = this->Makefile->GetCurrentSourceDirectory();
newname += "/" + args[2];
}
@@ -2383,7 +2357,7 @@ bool cmFileCommand::HandleRemove(std::vector<std::string> const& args,
i++; // Get rid of subcommand
for (; i != args.end(); ++i) {
std::string fileName = *i;
- if (!cmsys::SystemTools::FileIsFullPath(fileName.c_str())) {
+ if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
fileName = this->Makefile->GetCurrentSourceDirectory();
fileName += "/" + *i;
}
@@ -2425,7 +2399,7 @@ bool cmFileCommand::HandleCMakePathCommand(
if (!nativePath) {
cmSystemTools::ConvertToUnixSlashes(*j);
} else {
- *j = cmSystemTools::ConvertToOutputPath(j->c_str());
+ *j = cmSystemTools::ConvertToOutputPath(*j);
// remove double quotes in the path
cmsys::String& s = *j;
@@ -2626,6 +2600,9 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
std::string statusVar;
bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY");
const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO");
+ std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC");
+ std::string netrc_file =
+ this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE");
std::string expectedHash;
std::string hashMatchMSG;
std::unique_ptr<cmCryptoHash> hash;
@@ -2681,6 +2658,22 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
this->SetError("TLS_CAFILE missing file value.");
return false;
}
+ } else if (*i == "NETRC_FILE") {
+ ++i;
+ if (i != args.end()) {
+ netrc_file = *i;
+ } else {
+ this->SetError("DOWNLOAD missing file value for NETRC_FILE.");
+ return false;
+ }
+ } else if (*i == "NETRC") {
+ ++i;
+ if (i != args.end()) {
+ netrc_level = *i;
+ } else {
+ this->SetError("DOWNLOAD missing level value for NETRC.");
+ return false;
+ }
} else if (*i == "EXPECTED_MD5") {
++i;
if (i == args.end()) {
@@ -2742,7 +2735,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// and the existing file already has the expected hash, then simply
// return.
//
- if (cmSystemTools::FileExists(file.c_str()) && hash.get()) {
+ if (cmSystemTools::FileExists(file) && hash.get()) {
std::string msg;
std::string actualHash = hash->HashFile(file);
if (actualHash == expectedHash) {
@@ -2761,8 +2754,7 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
// as we receive downloaded bits from curl...
//
std::string dir = cmSystemTools::GetFilenamePath(file);
- if (!cmSystemTools::FileExists(dir.c_str()) &&
- !cmSystemTools::MakeDirectory(dir.c_str())) {
+ if (!cmSystemTools::FileExists(dir) && !cmSystemTools::MakeDirectory(dir)) {
std::string errstring = "DOWNLOAD error: cannot create directory '" + dir +
"' - Specify file by full path name and verify that you "
"have directory creation and file write privileges.";
@@ -2822,6 +2814,16 @@ bool cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args)
return false;
}
+ // check to see if netrc parameters have been specified
+ // local command args takes precedence over CMAKE_NETRC*
+ netrc_level = cmSystemTools::UpperCase(netrc_level);
+ std::string const& netrc_option_err =
+ cmCurlSetNETRCOption(curl, netrc_level, netrc_file);
+ if (!netrc_option_err.empty()) {
+ this->SetError(netrc_option_err);
+ return false;
+ }
+
cmFileCommandVectorOfChar chunkDebug;
res = ::curl_easy_setopt(curl, CURLOPT_WRITEDATA, &fout);
@@ -2964,6 +2966,9 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
std::string statusVar;
bool showProgress = false;
std::string userpwd;
+ std::string netrc_level = this->Makefile->GetSafeDefinition("CMAKE_NETRC");
+ std::string netrc_file =
+ this->Makefile->GetSafeDefinition("CMAKE_NETRC_FILE");
std::vector<std::string> curl_headers;
@@ -3000,6 +3005,22 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
statusVar = *i;
} else if (*i == "SHOW_PROGRESS") {
showProgress = true;
+ } else if (*i == "NETRC_FILE") {
+ ++i;
+ if (i != args.end()) {
+ netrc_file = *i;
+ } else {
+ this->SetError("UPLOAD missing file value for NETRC_FILE.");
+ return false;
+ }
+ } else if (*i == "NETRC") {
+ ++i;
+ if (i != args.end()) {
+ netrc_level = *i;
+ } else {
+ this->SetError("UPLOAD missing level value for NETRC.");
+ return false;
+ }
} else if (*i == "USERPWD") {
++i;
if (i == args.end()) {
@@ -3132,6 +3153,16 @@ bool cmFileCommand::HandleUploadCommand(std::vector<std::string> const& args)
check_curl_result(res, "UPLOAD cannot set user password: ");
}
+ // check to see if netrc parameters have been specified
+ // local command args takes precedence over CMAKE_NETRC*
+ netrc_level = cmSystemTools::UpperCase(netrc_level);
+ std::string const& netrc_option_err =
+ cmCurlSetNETRCOption(curl, netrc_level, netrc_file);
+ if (!netrc_option_err.empty()) {
+ this->SetError(netrc_option_err);
+ return false;
+ }
+
struct curl_slist* headers = nullptr;
for (std::string const& h : curl_headers) {
headers = ::curl_slist_append(headers, h.c_str());
diff --git a/Source/cmFilePathChecksum.cxx b/Source/cmFilePathChecksum.cxx
index f9afeefcd..f84360e7f 100644
--- a/Source/cmFilePathChecksum.cxx
+++ b/Source/cmFilePathChecksum.cxx
@@ -34,10 +34,10 @@ void cmFilePathChecksum::setupParentDirs(std::string const& currentSrcDir,
std::string const& projectSrcDir,
std::string const& projectBinDir)
{
- this->parentDirs[0].first = cmsys::SystemTools::GetRealPath(currentSrcDir);
- this->parentDirs[1].first = cmsys::SystemTools::GetRealPath(currentBinDir);
- this->parentDirs[2].first = cmsys::SystemTools::GetRealPath(projectSrcDir);
- this->parentDirs[3].first = cmsys::SystemTools::GetRealPath(projectBinDir);
+ this->parentDirs[0].first = cmSystemTools::GetRealPath(currentSrcDir);
+ this->parentDirs[1].first = cmSystemTools::GetRealPath(currentBinDir);
+ this->parentDirs[2].first = cmSystemTools::GetRealPath(projectSrcDir);
+ this->parentDirs[3].first = cmSystemTools::GetRealPath(projectBinDir);
this->parentDirs[0].second = "CurrentSource";
this->parentDirs[1].second = "CurrentBinary";
@@ -50,7 +50,7 @@ std::string cmFilePathChecksum::get(std::string const& filePath) const
std::string relPath;
std::string relSeed;
{
- std::string const fileReal = cmsys::SystemTools::GetRealPath(filePath);
+ std::string const fileReal = cmSystemTools::GetRealPath(filePath);
std::string parentDir;
// Find closest project parent directory
for (auto const& pDir : this->parentDirs) {
diff --git a/Source/cmFilePathChecksum.h b/Source/cmFilePathChecksum.h
index 48b5da0f0..30881ce90 100644
--- a/Source/cmFilePathChecksum.h
+++ b/Source/cmFilePathChecksum.h
@@ -29,13 +29,13 @@ public:
/// @brief Parent directories are empty
cmFilePathChecksum();
- /// @brief Initilizes the parent directories manually
+ /// @brief Initializes the parent directories manually
cmFilePathChecksum(std::string const& currentSrcDir,
std::string const& currentBinDir,
std::string const& projectSrcDir,
std::string const& projectBinDir);
- /// @brief Initilizes the parent directories from a makefile
+ /// @brief Initializes the parent directories from a makefile
cmFilePathChecksum(cmMakefile* makefile);
/// @brief Allows parent directories setup after construction
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index 814296201..4a467f384 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -314,7 +314,7 @@ void cmFindCommon::AddPathSuffix(std::string const& arg)
}
// Store the suffix.
- this->SearchPathSuffixes.push_back(suffix);
+ this->SearchPathSuffixes.push_back(std::move(suffix));
}
void AddTrailingSlash(std::string& s)
@@ -329,7 +329,7 @@ void cmFindCommon::ComputeFinalPaths()
std::set<std::string> ignored;
this->GetIgnoredPaths(ignored);
- // Combine the seperate path types, filtering out ignores
+ // Combine the separate path types, filtering out ignores
this->SearchPaths.clear();
std::vector<PathLabel>& allLabels = this->PathGroupLabelMap[PathGroup::All];
for (PathLabel const& l : allLabels) {
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index 758da2ce0..02bae828b 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -150,7 +150,7 @@ void cmFindLibraryCommand::AddArchitecturePath(
if (use_dirX) {
dirX += "/";
- this->SearchPaths.push_back(dirX);
+ this->SearchPaths.push_back(std::move(dirX));
}
if (use_dir) {
@@ -323,7 +323,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
}
regex += "$";
entry.Regex.compile(regex.c_str());
- this->Names.push_back(entry);
+ this->Names.push_back(std::move(entry));
}
void cmFindLibraryHelper::SetName(std::string const& name)
@@ -353,7 +353,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
if (name.TryRaw) {
this->TestPath = path;
this->TestPath += name.Raw;
- if (cmSystemTools::FileExists(this->TestPath.c_str(), true)) {
+ if (cmSystemTools::FileExists(this->TestPath, true)) {
this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
cmSystemTools::ConvertToUnixSlashes(this->BestPath);
return true;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 5a7265581..2f3a85b07 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -225,7 +225,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
std::set<std::string> optionalComponents;
// Always search directly in a generated path.
- this->SearchPathSuffixes.push_back("");
+ this->SearchPathSuffixes.emplace_back();
// Parse the arguments.
enum Doing
@@ -523,7 +523,7 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
config = cmSystemTools::LowerCase(n);
config += "-config.cmake";
- this->Configs.push_back(config);
+ this->Configs.push_back(std::move(config));
}
}
@@ -590,7 +590,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
}
- // Push on to the pacakge stack
+ // Push on to the package stack
this->Makefile->FindPackageModuleStack.push_back(this->Name);
}
@@ -660,7 +660,7 @@ bool cmFindPackageCommand::HandlePackageMode()
cmSystemTools::ConvertToUnixSlashes(dir);
// Treat relative paths with respect to the current source dir.
- if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(dir)) {
dir = "/" + dir;
dir = this->Makefile->GetCurrentSourceDirectory() + dir;
}
@@ -1346,10 +1346,10 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname,
cmSearchPath& outPaths)
{
// Parse the content of one package registry entry.
- if (cmSystemTools::FileIsFullPath(fname.c_str())) {
+ if (cmSystemTools::FileIsFullPath(fname)) {
// The first line in the stream is the full path to a file or
// directory containing the package.
- if (cmSystemTools::FileExists(fname.c_str())) {
+ if (cmSystemTools::FileExists(fname)) {
// The path exists. Look for the package here.
if (!cmSystemTools::FileIsDirectory(fname)) {
outPaths.AddPath(cmSystemTools::GetFilenamePath(fname));
@@ -1442,8 +1442,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
if (this->DebugMode) {
fprintf(stderr, "Checking file [%s]\n", file.c_str());
}
- if (cmSystemTools::FileExists(file.c_str(), true) &&
- this->CheckVersion(file)) {
+ if (cmSystemTools::FileExists(file, true) && this->CheckVersion(file)) {
return true;
}
}
@@ -1463,7 +1462,7 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
// Look for foo-config-version.cmake
std::string version_file = version_file_base;
version_file += "-version.cmake";
- if (!haveResult && cmSystemTools::FileExists(version_file.c_str(), true)) {
+ if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
}
@@ -1471,7 +1470,7 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
// Look for fooConfigVersion.cmake
version_file = version_file_base;
version_file += "Version.cmake";
- if (!haveResult && cmSystemTools::FileExists(version_file.c_str(), true)) {
+ if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
result = this->CheckVersionFile(version_file, version);
haveResult = true;
}
@@ -1484,7 +1483,7 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
ConfigFileInfo configFileInfo;
configFileInfo.filename = config_file;
configFileInfo.version = version;
- this->ConsideredConfigs.push_back(configFileInfo);
+ this->ConsideredConfigs.push_back(std::move(configFileInfo));
return result;
}
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index ea2641001..38ff2ed51 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -94,7 +94,7 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
std::string intPath = fpath;
intPath += "/Headers/";
intPath += fileName;
- if (cmSystemTools::FileExists(intPath.c_str())) {
+ if (cmSystemTools::FileExists(intPath)) {
if (this->IncludeFileInPath) {
return intPath;
}
@@ -128,7 +128,7 @@ std::string cmFindPathCommand::FindNormalHeader()
for (std::string const& sp : this->SearchPaths) {
tryPath = sp;
tryPath += n;
- if (cmSystemTools::FileExists(tryPath.c_str())) {
+ if (cmSystemTools::FileExists(tryPath)) {
if (this->IncludeFileInPath) {
return tryPath;
}
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 2059b3d65..1c6342841 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -22,7 +22,7 @@ struct cmFindProgramHelper
this->Extensions.push_back(".exe");
#endif
// Consider original name with no extensions.
- this->Extensions.push_back("");
+ this->Extensions.emplace_back();
}
// List of valid extensions.
diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx
index 542a86025..df288bd68 100644
--- a/Source/cmForEachCommand.cxx
+++ b/Source/cmForEachCommand.cxx
@@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
@@ -121,7 +122,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
}
// create a function blocker
- cmForEachFunctionBlocker* f = new cmForEachFunctionBlocker(this->Makefile);
+ auto f = cm::make_unique<cmForEachFunctionBlocker>(this->Makefile);
if (args.size() > 1) {
if (args[1] == "RANGE") {
int start = 0;
@@ -175,7 +176,7 @@ bool cmForEachCommand::InitialPass(std::vector<std::string> const& args,
} else {
f->Args = args;
}
- this->Makefile->AddFunctionBlocker(f);
+ this->Makefile->AddFunctionBlocker(f.release());
return true;
}
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index 81f1286d2..dd4f16bd9 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -17,14 +17,14 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
// If the file is a full path, include it directly.
if (cmSystemTools::FileIsFullPath(includeName)) {
fileName = includeName;
- return cmSystemTools::FileExists(fileName.c_str(), true);
+ return cmSystemTools::FileExists(fileName, true);
}
// Check for the file in the directory containing the including
// file.
std::string fullName = dir;
fullName += "/";
fullName += includeName;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ if (cmSystemTools::FileExists(fullName, true)) {
fileName = fullName;
return true;
}
@@ -34,7 +34,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
fullName = i;
fullName += "/";
fullName += includeName;
- if (cmSystemTools::FileExists(fullName.c_str(), true)) {
+ if (cmSystemTools::FileExists(fullName, true)) {
fileName = fullName;
return true;
}
diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx
index 6aa593cc0..c0a74a5f4 100644
--- a/Source/cmGeneratedFileStream.cxx
+++ b/Source/cmGeneratedFileStream.cxx
@@ -147,7 +147,7 @@ void cmGeneratedFileStreamBase::Open(const char* name)
cmSystemTools::RemoveFile(this->TempName);
std::string dir = cmSystemTools::GetFilenamePath(this->TempName);
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
}
bool cmGeneratedFileStreamBase::Close()
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 86991c1c5..64ec30ded 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -9,6 +9,7 @@
#include "assert.h"
#include "cmAlgorithms.h"
#include "cmGeneratorExpressionContext.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
#include "cmGeneratorExpressionParser.h"
@@ -202,7 +203,7 @@ static void prefixItems(const std::string& content, std::string& result,
for (std::string const& e : entries) {
result += sep;
sep = ";";
- if (!cmSystemTools::FileIsFullPath(e.c_str()) &&
+ if (!cmSystemTools::FileIsFullPath(e) &&
cmGeneratorExpression::Find(e) != 0) {
result += prefix;
}
@@ -385,3 +386,18 @@ void cmCompiledGeneratorExpression::GetMaxLanguageStandard(
mapping = it->second;
}
}
+
+const char* cmGeneratorExpressionInterpreter::Evaluate(
+ const char* expression, const std::string& property)
+{
+ if (this->Target.empty()) {
+ return this->EvaluateExpression(expression);
+ }
+
+ // Specify COMPILE_OPTIONS to DAGchecker, same semantic as COMPILE_FLAGS
+ cmGeneratorExpressionDAGChecker dagChecker(
+ this->Target, property == "COMPILE_FLAGS" ? "COMPILE_OPTIONS" : property,
+ nullptr, nullptr);
+
+ return this->EvaluateExpression(expression, &dagChecker);
+}
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index cface0d70..9fd53c67e 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -153,4 +153,89 @@ private:
bool EvaluateForBuildsystem;
};
+class cmGeneratorExpressionInterpreter
+{
+ CM_DISABLE_COPY(cmGeneratorExpressionInterpreter)
+
+public:
+ cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
+ cmGeneratorTarget* generatorTarget,
+ const std::string& config,
+ const std::string& target,
+ const std::string& lang)
+ : LocalGenerator(localGenerator)
+ , GeneratorTarget(generatorTarget)
+ , Config(config)
+ , Target(target)
+ , Language(lang)
+ {
+ }
+ cmGeneratorExpressionInterpreter(cmLocalGenerator* localGenerator,
+ cmGeneratorTarget* generatorTarget,
+ const std::string& config)
+ : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget, config,
+ std::string(), std::string())
+ {
+ }
+
+ const char* Evaluate(const char* expression)
+ {
+ return this->EvaluateExpression(expression);
+ }
+ const char* Evaluate(const std::string& expression)
+ {
+ return this->Evaluate(expression.c_str());
+ }
+ const char* Evaluate(const char* expression, const std::string& property);
+ const char* Evaluate(const std::string& expression,
+ const std::string& property)
+ {
+ return this->Evaluate(expression.c_str(), property);
+ }
+
+protected:
+ cmGeneratorExpression& GetGeneratorExpression()
+ {
+ return this->GeneratorExpression;
+ }
+
+ cmCompiledGeneratorExpression& GetCompiledGeneratorExpression()
+ {
+ return *(this->CompiledGeneratorExpression);
+ }
+
+ cmLocalGenerator* GetLocalGenerator() { return this->LocalGenerator; }
+
+ cmGeneratorTarget* GetGeneratorTarget() { return this->GeneratorTarget; }
+
+ const std::string& GetTargetName() const { return this->Target; }
+ const std::string& GetLanguage() const { return this->Language; }
+
+ const char* EvaluateExpression(
+ const char* expression,
+ cmGeneratorExpressionDAGChecker* dagChecker = nullptr)
+ {
+ this->CompiledGeneratorExpression =
+ this->GeneratorExpression.Parse(expression);
+
+ if (dagChecker == nullptr) {
+ return this->CompiledGeneratorExpression->Evaluate(
+ this->LocalGenerator, this->Config, false, this->GeneratorTarget);
+ }
+
+ return this->CompiledGeneratorExpression->Evaluate(
+ this->LocalGenerator, this->Config, false, this->GeneratorTarget,
+ dagChecker, this->Language);
+ }
+
+private:
+ cmGeneratorExpression GeneratorExpression;
+ std::unique_ptr<cmCompiledGeneratorExpression> CompiledGeneratorExpression;
+ cmLocalGenerator* LocalGenerator = nullptr;
+ cmGeneratorTarget* GeneratorTarget = nullptr;
+ std::string Config;
+ std::string Target;
+ std::string Language;
+};
+
#endif
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 87b6b342d..c54414193 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -13,6 +13,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocationKind.h"
#include "cmSystemTools.h"
#include "cmake.h"
@@ -102,7 +103,8 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
for (std::string const& le : enabledLanguages) {
std::string name = this->OutputFileExpr->Evaluate(
lg, config, false, nullptr, nullptr, nullptr, le);
- cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(name);
+ cmSourceFile* sf = lg->GetMakefile()->GetOrCreateSource(
+ name, false, cmSourceFileLocationKind::Known);
sf->SetProperty("GENERATED", "1");
gg->SetFilenameTargetDepends(
@@ -153,7 +155,7 @@ void cmGeneratorExpressionEvaluationFile::Generate(cmLocalGenerator* lg)
lg->GetMakefile()->GetConfigurations(allConfigs);
if (allConfigs.empty()) {
- allConfigs.push_back("");
+ allConfigs.emplace_back();
}
std::vector<std::string> enabledLanguages;
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index c73d48601..dbc6840fc 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -132,9 +132,8 @@ std::string GeneratorExpressionContent::EvaluateParameters(
int counter = 1;
for (; pit != pend; ++pit, ++counter) {
if (acceptsArbitraryContent && counter == numExpected) {
- std::string lastParam = this->ProcessArbitraryContent(
- node, identifier, context, dagChecker, pit);
- parameters.push_back(lastParam);
+ parameters.push_back(this->ProcessArbitraryContent(
+ node, identifier, context, dagChecker, pit));
return std::string();
}
std::string parameter;
@@ -148,7 +147,7 @@ std::string GeneratorExpressionContent::EvaluateParameters(
return std::string();
}
}
- parameters.push_back(parameter);
+ parameters.push_back(std::move(parameter));
}
}
diff --git a/Source/cmGeneratorExpressionLexer.cxx b/Source/cmGeneratorExpressionLexer.cxx
index 931fd4d62..e37f165a8 100644
--- a/Source/cmGeneratorExpressionLexer.cxx
+++ b/Source/cmGeneratorExpressionLexer.cxx
@@ -12,8 +12,7 @@ static void InsertText(const char* upto, const char* c,
std::vector<cmGeneratorExpressionToken>& result)
{
if (upto != c) {
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::Text, upto, c - upto));
+ result.emplace_back(cmGeneratorExpressionToken::Text, upto, c - upto);
}
}
@@ -22,6 +21,12 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
{
std::vector<cmGeneratorExpressionToken> result;
+ if (input.find('$') == std::string::npos) {
+ result.push_back(cmGeneratorExpressionToken(
+ cmGeneratorExpressionToken::Text, input.c_str(), input.size()));
+ return result;
+ }
+
const char* c = input.c_str();
const char* upto = c;
@@ -30,8 +35,8 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
case '$':
if (c[1] == '<') {
InsertText(upto, c, result);
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::BeginExpression, c, 2));
+ result.emplace_back(cmGeneratorExpressionToken::BeginExpression, c,
+ 2);
upto = c + 2;
++c;
SawBeginExpression = true;
@@ -39,21 +44,18 @@ std::vector<cmGeneratorExpressionToken> cmGeneratorExpressionLexer::Tokenize(
break;
case '>':
InsertText(upto, c, result);
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::EndExpression, c, 1));
+ result.emplace_back(cmGeneratorExpressionToken::EndExpression, c, 1);
upto = c + 1;
SawGeneratorExpression = SawBeginExpression;
break;
case ':':
InsertText(upto, c, result);
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::ColonSeparator, c, 1));
+ result.emplace_back(cmGeneratorExpressionToken::ColonSeparator, c, 1);
upto = c + 1;
break;
case ',':
InsertText(upto, c, result);
- result.push_back(cmGeneratorExpressionToken(
- cmGeneratorExpressionToken::CommaSeparator, c, 1));
+ result.emplace_back(cmGeneratorExpressionToken::CommaSeparator, c, 1);
upto = c + 1;
break;
default:
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index fea20ba87..c1f1ee489 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -805,7 +805,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
const std::vector<std::string>& parameters,
cmGeneratorExpressionContext* context,
const GeneratorExpressionContent* content,
- cmGeneratorExpressionDAGChecker* dagChecker) const override
+ cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
{
if (context->Language.empty()) {
reportError(
@@ -827,31 +827,15 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode
return std::string();
}
std::string genName = gg->GetName();
- if (genName.find("Visual Studio") != std::string::npos) {
+ if (genName.find("Makefiles") == std::string::npos &&
+ genName.find("Ninja") == std::string::npos &&
+ genName.find("Visual Studio") == std::string::npos &&
+ genName.find("Xcode") == std::string::npos &&
+ genName.find("Watcom WMake") == std::string::npos) {
reportError(context, content->GetOriginalExpression(),
- "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
- "generators.");
+ "$<COMPILE_LANGUAGE:...> not supported for this generator.");
return std::string();
}
- if (genName.find("Xcode") != std::string::npos) {
- if (dagChecker && (dagChecker->EvaluatingCompileDefinitions() ||
- dagChecker->EvaluatingIncludeDirectories())) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
- "with the Xcode generator.");
- return std::string();
- }
- } else {
- if (genName.find("Makefiles") == std::string::npos &&
- genName.find("Ninja") == std::string::npos &&
- genName.find("Watcom WMake") == std::string::npos) {
- reportError(
- context, content->GetOriginalExpression(),
- "$<COMPILE_LANGUAGE:...> not supported for this generator.");
- return std::string();
- }
- }
if (parameters.empty()) {
return context->Language;
}
@@ -963,7 +947,8 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
"Target name not supported.");
return std::string();
}
- if (propertyName == "ALIASED_TARGET") {
+ static const std::string propALIASED_TARGET = "ALIASED_TARGET";
+ if (propertyName == propALIASED_TARGET) {
if (context->LG->GetMakefile()->IsAlias(targetName)) {
if (cmGeneratorTarget* tgt =
context->LG->FindGeneratorTargetToUse(targetName)) {
@@ -1035,7 +1020,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
// No error. We just skip cyclic references.
return std::string();
case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- for (size_t i = 1; i < cmArraySize(targetPropertyTransitiveWhitelist);
+ for (size_t i = 1; i < cm::size(targetPropertyTransitiveWhitelist);
++i) {
if (targetPropertyTransitiveWhitelist[i] == propertyName) {
// No error. We're not going to find anything new here.
@@ -1090,8 +1075,7 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
// Note that the above macro terminates with an else
- /* else */ if (cmHasLiteralPrefix(propertyName.c_str(),
- "COMPILE_DEFINITIONS_")) {
+ /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
cmPolicies::PolicyStatus polSt =
context->LG->GetPolicyStatus(cmPolicies::CMP0043);
if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
@@ -1443,7 +1427,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode
context->HadContextSensitiveCondition = true;
context->HadHeadSensitiveCondition = true;
- for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i) {
+ for (size_t i = 1; i < cm::size(targetPolicyWhitelist); ++i) {
const char* policy = targetPolicyWhitelist[i];
if (parameters.front() == policy) {
cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator();
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 103d0340e..2bb01b29e 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -384,14 +384,15 @@ static void handleSystemIncludesDep(
cmLocalGenerator* lg, cmGeneratorTarget const* depTgt,
const std::string& config, cmGeneratorTarget const* headTarget,
cmGeneratorExpressionDAGChecker* dagChecker,
- std::vector<std::string>& result, bool excludeImported)
+ std::vector<std::string>& result, bool excludeImported,
+ std::string const& language)
{
if (const char* dirs =
depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) {
cmGeneratorExpression ge;
cmSystemTools::ExpandListArgument(
ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
- dagChecker),
+ dagChecker, language),
result);
}
if (!depTgt->IsImported() || excludeImported) {
@@ -403,7 +404,7 @@ static void handleSystemIncludesDep(
cmGeneratorExpression ge;
cmSystemTools::ExpandListArgument(
ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt,
- dagChecker),
+ dagChecker, language),
result);
}
}
@@ -445,7 +446,7 @@ void cmGeneratorTarget::ComputeObjectMapping()
std::vector<std::string> configs;
this->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
for (std::string const& c : configs) {
std::vector<cmSourceFile const*> sourceFiles;
@@ -735,7 +736,8 @@ const char* cmGeneratorTarget::GetLocationForBuild() const
}
bool cmGeneratorTarget::IsSystemIncludeDirectory(
- const std::string& dir, const std::string& config) const
+ const std::string& dir, const std::string& config,
+ const std::string& language) const
{
assert(this->GetType() != cmStateEnums::INTERFACE_LIBRARY);
std::string config_upper;
@@ -758,7 +760,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
cmGeneratorExpression ge;
cmSystemTools::ExpandListArgument(
ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, this,
- &dagChecker),
+ &dagChecker, language),
result);
}
@@ -766,7 +768,7 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory(
this->GetLinkImplementationClosure(config);
for (cmGeneratorTarget const* dep : deps) {
handleSystemIncludesDep(this->LocalGenerator, dep, config, this,
- &dagChecker, result, excludeImported);
+ &dagChecker, result, excludeImported, language);
}
std::for_each(result.begin(), result.end(),
@@ -842,7 +844,7 @@ static bool processSources(
return contextDependent;
}
- if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src.c_str())) {
+ if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
std::ostringstream err;
if (!targetName.empty()) {
err << "Target \"" << targetName
@@ -1101,8 +1103,7 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
}
// Save this classified source file in the result vector.
- SourceAndKind entry = { sf, kind };
- files.Sources.push_back(entry);
+ files.Sources.push_back({ sf, kind });
}
if (!badObjLib.empty()) {
@@ -1143,7 +1144,7 @@ void cmGeneratorTarget::ComputeAllConfigSources() const
AllConfigSource acs;
acs.Source = src.Source;
acs.Kind = src.Kind;
- this->AllConfigSources.push_back(acs);
+ this->AllConfigSources.push_back(std::move(acs));
std::map<cmSourceFile const*, size_t>::value_type entry(
src.Source, this->AllConfigSources.size() - 1);
mi = index.insert(entry).first;
@@ -1529,7 +1530,8 @@ std::string cmGeneratorTarget::GetAppBundleDirectory(
ext = "app";
}
fpath += ext;
- if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddContentLevel(level) &&
+ !this->Makefile->PlatformIsAppleEmbedded()) {
fpath += "/Contents";
if (shouldAddFullLevel(level)) {
fpath += "/MacOS";
@@ -1559,7 +1561,8 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(
}
}
fpath += ext;
- if (shouldAddContentLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddContentLevel(level) &&
+ !this->Makefile->PlatformIsAppleEmbedded()) {
fpath += "/Contents";
if (shouldAddFullLevel(level)) {
fpath += "/MacOS";
@@ -1579,7 +1582,8 @@ std::string cmGeneratorTarget::GetFrameworkDirectory(
ext = "framework";
}
fpath += ext;
- if (shouldAddFullLevel(level) && !this->Makefile->PlatformIsAppleIos()) {
+ if (shouldAddFullLevel(level) &&
+ !this->Makefile->PlatformIsAppleEmbedded()) {
fpath += "/Versions/";
fpath += this->GetFrameworkVersion();
}
@@ -2110,7 +2114,7 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
std::vector<std::string> configs;
this->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
std::set<cmSourceFile*> emitted;
for (std::string const& c : configs) {
@@ -2166,7 +2170,7 @@ void cmTargetTraceDependencies::Trace()
// Queue the source needed to generate this file, if any.
this->FollowName(sf->GetFullPath());
- // Queue dependencies added programatically by commands.
+ // Queue dependencies added programmatically by commands.
this->FollowNames(sf->GetDepends());
// Queue custom command dependencies.
@@ -2235,7 +2239,7 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
// If we find the target and the dep was given as a full path,
// then make sure it was not a full path to something else, and
// the fact that the name matched a target was just a coincidence.
- if (cmSystemTools::FileIsFullPath(dep.c_str())) {
+ if (cmSystemTools::FileIsFullPath(dep)) {
if (t->GetType() >= cmStateEnums::EXECUTABLE &&
t->GetType() <= cmStateEnums::MODULE_LIBRARY) {
// This is really only for compatibility so we do not need to
@@ -2303,7 +2307,7 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
std::set<std::string> emitted;
this->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
for (std::string const& conf : configs) {
this->FollowCommandDepends(cc, conf, emitted);
@@ -2435,7 +2439,7 @@ static void processIncludeDirectories(
std::string usedIncludes;
for (std::string& entryInclude : entryIncludes) {
- if (fromImported && !cmSystemTools::FileExists(entryInclude.c_str())) {
+ if (fromImported && !cmSystemTools::FileExists(entryInclude)) {
std::ostringstream e;
cmake::MessageType messageType = cmake::FATAL_ERROR;
if (checkCMP0027) {
@@ -2467,7 +2471,7 @@ static void processIncludeDirectories(
return;
}
- if (!cmSystemTools::FileIsFullPath(entryInclude.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(entryInclude)) {
std::ostringstream e;
bool noMessage = false;
cmake::MessageType messageType = cmake::FATAL_ERROR;
@@ -3004,7 +3008,7 @@ void cmGeneratorTarget::GetLibraryNames(std::string& name, std::string& soName,
if (this->IsFrameworkOnApple()) {
realName = prefix;
- if (!this->Makefile->PlatformIsAppleIos()) {
+ if (!this->Makefile->PlatformIsAppleEmbedded()) {
realName += "Versions/";
realName += this->GetFrameworkVersion();
realName += "/";
@@ -3538,7 +3542,7 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
for (std::string const& p : props) {
std::string pname = cmSystemTools::HelpFileName(p);
std::string pfile = pdir + pname + ".rst";
- if (cmSystemTools::FileExists(pfile.c_str(), true)) {
+ if (cmSystemTools::FileExists(pfile, true)) {
std::ostringstream e;
e << "Target \"" << dependee->GetName() << "\" has property \"" << p
<< "\" listed in its " << propName
@@ -3614,13 +3618,13 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
const cmComputeLinkInformation::ItemVector& deps = info->GetItems();
std::set<std::string> emittedBools;
- static std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
+ static const std::string strBool = "COMPATIBLE_INTERFACE_BOOL";
std::set<std::string> emittedStrings;
- static std::string strString = "COMPATIBLE_INTERFACE_STRING";
+ static const std::string strString = "COMPATIBLE_INTERFACE_STRING";
std::set<std::string> emittedMinNumbers;
- static std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
+ static const std::string strNumMin = "COMPATIBLE_INTERFACE_NUMBER_MIN";
std::set<std::string> emittedMaxNumbers;
- static std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
+ static const std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX";
for (auto const& dep : deps) {
if (!dep.Target) {
@@ -4198,7 +4202,7 @@ void cmGeneratorTarget::LookupLinkItems(std::vector<std::string> const& names,
if (name == this->GetName() || name.empty()) {
continue;
}
- items.push_back(cmLinkItem(name, this->FindTargetToLink(name)));
+ items.emplace_back(name, this->FindTargetToLink(name));
}
}
@@ -4985,7 +4989,7 @@ bool cmGeneratorTarget::GetConfigCommonSourceFiles(
std::vector<std::string> configs;
this->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
std::vector<std::string>::const_iterator it = configs.begin();
@@ -5133,7 +5137,12 @@ void cmGeneratorTarget::GetLanguages(std::set<std::string>& languages,
std::string objLib = extObj->GetObjectLibrary();
if (cmGeneratorTarget* tgt =
this->LocalGenerator->FindGeneratorTargetToUse(objLib)) {
- objectLibraries.push_back(tgt);
+ auto const objLibIt =
+ std::find_if(objectLibraries.cbegin(), objectLibraries.cend(),
+ [tgt](cmGeneratorTarget* t) { return t == tgt; });
+ if (objectLibraries.cend() == objLibIt) {
+ objectLibraries.push_back(tgt);
+ }
}
}
}
@@ -5149,7 +5158,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLanguages(
std::set<std::string> languages;
// Get languages used in our source files.
this->GetLanguages(languages, config);
- // Copy the set of langauges to the link implementation.
+ // Copy the set of languages to the link implementation.
impl.Languages.insert(impl.Languages.begin(), languages.begin(),
languages.end());
}
@@ -5268,8 +5277,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
}
// The entry is meant for this configuration.
- impl.Libraries.push_back(cmLinkImplItem(
- name, this->FindTargetToLink(name), *btIt, evaluated != *le));
+ impl.Libraries.emplace_back(name, this->FindTargetToLink(name), *btIt,
+ evaluated != *le);
}
std::set<std::string> const& seenProps = cge->GetSeenTargetProperties();
@@ -5296,8 +5305,8 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries(
continue;
}
// Support OLD behavior for CMP0003.
- impl.WrongConfigLibraries.push_back(
- cmLinkItem(name, this->FindTargetToLink(name)));
+ impl.WrongConfigLibraries.emplace_back(name,
+ this->FindTargetToLink(name));
}
}
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 1ee8a16fb..2f6ce33f1 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -413,7 +413,8 @@ public:
const std::string& language) const;
bool IsSystemIncludeDirectory(const std::string& dir,
- const std::string& config) const;
+ const std::string& config,
+ const std::string& language) const;
/** Add the target output files to the global generator manifest. */
void ComputeTargetManifest(const std::string& config) const;
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index a8cf6ab9c..bf464d9e4 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -34,7 +34,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass(
}
std::string sd = *i;
// make sure the start dir is a full path
- if (!cmSystemTools::FileIsFullPath(sd.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(sd)) {
sd = this->Makefile->GetCurrentSourceDirectory();
sd += "/";
sd += *i;
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 4494c3e87..1d812bd28 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -206,7 +206,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode()
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
std::string dir = this->Name;
- if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(dir)) {
dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += this->Name;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index a31e415b8..270413c48 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -486,14 +486,14 @@ void cmGhsMultiTargetGenerator::WriteSources(
for (std::vector<cmSourceFile*>::const_iterator si = objectSources.begin();
si != objectSources.end(); ++si) {
std::vector<cmSourceGroup> sourceGroups(this->Makefile->GetSourceGroups());
- char const* sourceFullPath = (*si)->GetFullPath().c_str();
+ std::string const& sourceFullPath = (*si)->GetFullPath();
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,
- this->LocalGenerator->GetBinaryDirectory(), sgPath,
+ this->LocalGenerator->GetBinaryDirectory().c_str(), sgPath,
GhsMultiGpj::SUBPROJECT, this->RelBuildFilePath);
std::string fullSourcePath((*si)->GetFullPath());
@@ -604,11 +604,11 @@ std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory(
dir_max += "/";
std::vector<cmSourceGroup> sourceGroups(
localGhsMultiGenerator->GetMakefile()->GetSourceGroups());
- char const* const sourceFullPath = sourceFile->GetFullPath().c_str();
+ std::string const& sourceFullPath = sourceFile->GetFullPath();
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 05efff317..c805b98d7 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -21,6 +21,7 @@
#include "cmComputeTargetDepends.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
+#include "cmDuration.h"
#include "cmExportBuildFileGenerator.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -33,7 +34,7 @@
#include "cmMakefile.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
-#include "cmQtAutoGeneratorInitializer.h"
+#include "cmQtAutoGenInitializer.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
@@ -87,7 +88,7 @@ cmGlobalGenerator::cmGlobalGenerator(cmake* cm)
this->InstallTargetEnabled = false;
// how long to let try compiles run
- this->TryCompileTimeout = 0;
+ this->TryCompileTimeout = cmDuration::zero();
this->ExtraGenerator = nullptr;
this->CurrentConfigureMakefile = nullptr;
@@ -111,6 +112,26 @@ cmGlobalGenerator::~cmGlobalGenerator()
delete this->ExtraGenerator;
}
+bool cmGlobalGenerator::SetGeneratorInstance(std::string const& i,
+ cmMakefile* mf)
+{
+ if (i.empty()) {
+ return true;
+ }
+
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "does not support instance specification, but instance\n"
+ " " << i << "\n"
+ "was specified.";
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+}
+
bool cmGlobalGenerator::SetGeneratorPlatform(std::string const& p,
cmMakefile* mf)
{
@@ -261,6 +282,43 @@ void cmGlobalGenerator::ForceLinkerLanguages()
{
}
+bool cmGlobalGenerator::CheckTargetsForMissingSources() const
+{
+ bool failed = false;
+ for (cmLocalGenerator* localGen : this->LocalGenerators) {
+ const std::vector<cmGeneratorTarget*>& targets =
+ localGen->GetGeneratorTargets();
+
+ for (cmGeneratorTarget* target : targets) {
+ if (target->GetType() == cmStateEnums::TargetType::GLOBAL_TARGET ||
+ target->GetType() == cmStateEnums::TargetType::INTERFACE_LIBRARY ||
+ target->GetType() == cmStateEnums::TargetType::UTILITY) {
+ continue;
+ }
+
+ std::vector<std::string> configs;
+ target->Makefile->GetConfigurations(configs);
+ std::vector<cmSourceFile*> srcs;
+ if (configs.empty()) {
+ target->GetSourceFiles(srcs, "");
+ } else {
+ for (std::vector<std::string>::const_iterator ci = configs.begin();
+ ci != configs.end() && srcs.empty(); ++ci) {
+ target->GetSourceFiles(srcs, *ci);
+ }
+ }
+ if (srcs.empty()) {
+ std::ostringstream e;
+ e << "No SOURCES given to target: " << target->GetName();
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ target->GetBacktrace());
+ failed = true;
+ }
+ }
+ }
+ return failed;
+}
+
bool cmGlobalGenerator::IsExportedTargetsFile(
const std::string& filename) const
{
@@ -452,7 +510,7 @@ void cmGlobalGenerator::EnableLanguage(
bool const readCMakeSystem = !mf->GetDefinition("CMAKE_SYSTEM_LOADED");
if (readCMakeSystem) {
fpath += "/CMakeSystem.cmake";
- if (cmSystemTools::FileExists(fpath.c_str())) {
+ if (cmSystemTools::FileExists(fpath)) {
mf->ReadListFile(fpath.c_str());
}
}
@@ -491,6 +549,13 @@ void cmGlobalGenerator::EnableLanguage(
}
if (readCMakeSystem) {
+ // Tell the generator about the instance, if any.
+ std::string instance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
+ if (!this->SetGeneratorInstance(instance, mf)) {
+ cmSystemTools::SetFatalErrorOccured();
+ return;
+ }
+
// Find the native build tool for this generator.
if (!this->FindMakeProgram(mf)) {
return;
@@ -558,7 +623,7 @@ void cmGlobalGenerator::EnableLanguage(
// If the existing build tree was already configured with this
// version of CMake then try to load the configured file first
// to avoid duplicate compiler tests.
- if (cmSystemTools::FileExists(fpath.c_str())) {
+ if (cmSystemTools::FileExists(fpath)) {
if (!mf->ReadListFile(fpath.c_str())) {
cmSystemTools::Error("Could not find cmake module file: ",
fpath.c_str());
@@ -777,7 +842,7 @@ void cmGlobalGenerator::EnableLanguage(
projectCompatibility += "/Modules/";
projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
projectCompatibility += "Compatibility.cmake";
- if (cmSystemTools::FileExists(projectCompatibility.c_str())) {
+ if (cmSystemTools::FileExists(projectCompatibility)) {
mf->ReadListFile(projectCompatibility.c_str());
}
// Inform any extra generator of the new language.
@@ -898,7 +963,7 @@ std::string cmGlobalGenerator::GetLanguageOutputExtension(
}
} else {
// if no language is found then check to see if it is already an
- // ouput extension for some language. In that case it should be ignored
+ // output extension for some language. In that case it should be ignored
// and in this map, so it will not be compiled but will just be used.
std::string const& ext = source.GetExtension();
if (!ext.empty()) {
@@ -1140,7 +1205,7 @@ void cmGlobalGenerator::Configure()
f += this->CMakeInstance->GetCMakeFilesDirectory();
f += "/";
f += *log;
- if (cmSystemTools::FileExists(f.c_str())) {
+ if (cmSystemTools::FileExists(f)) {
msg << "\nSee also \"" << f << "\".";
}
}
@@ -1250,7 +1315,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
@@ -1271,10 +1339,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) {
@@ -1292,6 +1361,11 @@ bool cmGlobalGenerator::Compute()
localGen->TraceDependencies();
}
+ // Make sure that all (non-imported) targets have source files added!
+ if (this->CheckTargetsForMissingSources()) {
+ return false;
+ }
+
this->ForceLinkerLanguages();
// Compute the manifest of main targets generated.
@@ -1400,9 +1474,10 @@ bool cmGlobalGenerator::ComputeTargetDepends()
return true;
}
-cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
+std::vector<std::unique_ptr<cmQtAutoGenInitializer>>
+cmGlobalGenerator::CreateQtAutoGenInitializers()
{
- cmQtAutoGenDigestUPV autogenDigests;
+ std::vector<std::unique_ptr<cmQtAutoGenInitializer>> autogenInits;
#ifdef CMAKE_BUILD_WITH_CMAKE
for (cmLocalGenerator* localGen : this->LocalGenerators) {
@@ -1432,31 +1507,18 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets()
}
std::string qtVersionMajor =
- cmQtAutoGeneratorInitializer::GetQtMajorVersion(target);
+ cmQtAutoGenInitializer::GetQtMajorVersion(target);
// don't do anything if there is no Qt4 or Qt5Core (which contains moc)
if (qtVersionMajor != "4" && qtVersionMajor != "5") {
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 cmQtAutoGenInitializer(
+ target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor));
}
}
- // Initialize autogen targets
- for (const cmQtAutoGenDigestUP& digest : autogenDigests) {
- cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest);
- }
#endif
- return autogenDigests;
+ return autogenInits;
}
cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer(
@@ -1740,7 +1802,7 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
const std::string& target, std::string& output,
const std::string& makeCommandCSTR,
const std::string& config, bool clean, bool fast,
- bool verbose, double timeout,
+ bool verbose, cmDuration timeout,
cmSystemTools::OutputOption outputflag,
std::vector<std::string> const& nativeOptions)
{
@@ -1824,12 +1886,22 @@ int cmGlobalGenerator::Build(const std::string& /*unused*/,
return retVal;
}
+bool cmGlobalGenerator::Open(const std::string& bindir,
+ const std::string& projectName, bool dryRun)
+{
+ if (this->ExtraGenerator) {
+ return this->ExtraGenerator->Open(bindir, projectName, dryRun);
+ }
+
+ return false;
+}
+
std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
const std::string& target, const std::string& config,
const std::string& native, bool ignoreErrors)
{
std::string makeCommand = cmSystemTools::GetCMakeCommand();
- makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand.c_str());
+ makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand);
makeCommand += " --build .";
if (!config.empty()) {
makeCommand += " --config \"";
@@ -2141,6 +2213,45 @@ inline std::string removeQuotes(const std::string& s)
return s;
}
+bool cmGlobalGenerator::CheckCMP0037(std::string const& targetName,
+ std::string const& reason) const
+{
+ cmTarget* tgt = this->FindTarget(targetName);
+ if (!tgt) {
+ return true;
+ }
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ std::ostringstream e;
+ bool issueMessage = false;
+ switch (tgt->GetPolicyStatusCMP0037()) {
+ case cmPolicies::WARN:
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
+ issueMessage = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ issueMessage = true;
+ messageType = cmake::FATAL_ERROR;
+ break;
+ }
+ if (issueMessage) {
+ e << "The target name \"" << targetName << "\" is reserved " << reason
+ << ".";
+ if (messageType == cmake::AUTHOR_WARNING) {
+ e << " It may result in undefined behavior.";
+ }
+ this->GetCMakeInstance()->IssueMessage(messageType, e.str(),
+ tgt->GetBacktrace());
+ if (messageType == cmake::FATAL_ERROR) {
+ return false;
+ }
+ }
+ return true;
+}
+
void cmGlobalGenerator::CreateDefaultGlobalTargets(
std::vector<GlobalTargetInfo>& targets)
{
@@ -2156,6 +2267,20 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
std::vector<GlobalTargetInfo>& targets)
{
cmMakefile* mf = this->Makefiles[0];
+ std::string configFile = mf->GetCurrentBinaryDirectory();
+ configFile += "/CPackConfig.cmake";
+ if (!cmSystemTools::FileExists(configFile)) {
+ return;
+ }
+
+ const char* reservedTargets[] = { "package", "PACKAGE" };
+ for (const char* const* tn = cm::cbegin(reservedTargets);
+ tn != cm::cend(reservedTargets); ++tn) {
+ if (!this->CheckCMP0037(*tn, "when CPack packaging is enabled")) {
+ return;
+ }
+ }
+
const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
GlobalTargetInfo gti;
gti.Name = this->GetPackageTargetName();
@@ -2169,11 +2294,8 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
singleLine.push_back(cmakeCfgIntDir);
}
singleLine.push_back("--config");
- std::string configFile = mf->GetCurrentBinaryDirectory();
- configFile += "/CPackConfig.cmake";
- std::string relConfigFile = "./CPackConfig.cmake";
- singleLine.push_back(relConfigFile);
- gti.CommandLines.push_back(singleLine);
+ singleLine.push_back("./CPackConfig.cmake");
+ gti.CommandLines.push_back(std::move(singleLine));
if (this->GetPreinstallTargetName()) {
gti.Depends.push_back(this->GetPreinstallTargetName());
} else {
@@ -2183,111 +2305,131 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
gti.Depends.push_back(this->GetAllTargetName());
}
}
- if (cmSystemTools::FileExists(configFile.c_str())) {
- targets.push_back(gti);
- }
+ targets.push_back(std::move(gti));
}
void cmGlobalGenerator::AddGlobalTarget_PackageSource(
std::vector<GlobalTargetInfo>& targets)
{
- cmMakefile* mf = this->Makefiles[0];
const char* packageSourceTargetName = this->GetPackageSourceTargetName();
- if (packageSourceTargetName) {
- GlobalTargetInfo gti;
- gti.Name = packageSourceTargetName;
- gti.Message = "Run CPack packaging tool for source...";
- gti.WorkingDir = mf->GetCurrentBinaryDirectory();
- gti.UsesTerminal = true;
- cmCustomCommandLine singleLine;
- singleLine.push_back(cmSystemTools::GetCPackCommand());
- singleLine.push_back("--config");
- std::string configFile = mf->GetCurrentBinaryDirectory();
- configFile += "/CPackSourceConfig.cmake";
- std::string relConfigFile = "./CPackSourceConfig.cmake";
- singleLine.push_back(relConfigFile);
- if (cmSystemTools::FileExists(configFile.c_str())) {
- singleLine.push_back(configFile);
- gti.CommandLines.push_back(singleLine);
- targets.push_back(gti);
+ if (!packageSourceTargetName) {
+ return;
+ }
+
+ cmMakefile* mf = this->Makefiles[0];
+ std::string configFile = mf->GetCurrentBinaryDirectory();
+ configFile += "/CPackSourceConfig.cmake";
+ if (!cmSystemTools::FileExists(configFile)) {
+ return;
+ }
+
+ const char* reservedTargets[] = { "package_source" };
+ for (const char* const* tn = cm::cbegin(reservedTargets);
+ tn != cm::cend(reservedTargets); ++tn) {
+ if (!this->CheckCMP0037(*tn, "when CPack source packaging is enabled")) {
+ return;
}
}
+
+ GlobalTargetInfo gti;
+ gti.Name = packageSourceTargetName;
+ gti.Message = "Run CPack packaging tool for source...";
+ gti.WorkingDir = mf->GetCurrentBinaryDirectory();
+ gti.UsesTerminal = true;
+ cmCustomCommandLine singleLine;
+ singleLine.push_back(cmSystemTools::GetCPackCommand());
+ singleLine.push_back("--config");
+ singleLine.push_back("./CPackSourceConfig.cmake");
+ singleLine.push_back(std::move(configFile));
+ gti.CommandLines.push_back(std::move(singleLine));
+ targets.push_back(std::move(gti));
}
void cmGlobalGenerator::AddGlobalTarget_Test(
std::vector<GlobalTargetInfo>& targets)
{
cmMakefile* mf = this->Makefiles[0];
- const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
- if (mf->IsOn("CMAKE_TESTING_ENABLED")) {
- GlobalTargetInfo gti;
- gti.Name = this->GetTestTargetName();
- gti.Message = "Running tests...";
- gti.UsesTerminal = true;
- cmCustomCommandLine singleLine;
- singleLine.push_back(cmSystemTools::GetCTestCommand());
- singleLine.push_back("--force-new-ctest-process");
- if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
- singleLine.push_back("-C");
- singleLine.push_back(cmakeCfgIntDir);
- } else // TODO: This is a hack. Should be something to do with the
- // generator
- {
- singleLine.push_back("$(ARGS)");
+ if (!mf->IsOn("CMAKE_TESTING_ENABLED")) {
+ return;
+ }
+
+ const char* reservedTargets[] = { "test", "RUN_TESTS" };
+ for (const char* const* tn = cm::cbegin(reservedTargets);
+ tn != cm::cend(reservedTargets); ++tn) {
+ if (!this->CheckCMP0037(*tn, "when CTest testing is enabled")) {
+ return;
}
- gti.CommandLines.push_back(singleLine);
- targets.push_back(gti);
}
+
+ const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir();
+ GlobalTargetInfo gti;
+ gti.Name = this->GetTestTargetName();
+ gti.Message = "Running tests...";
+ gti.UsesTerminal = true;
+ cmCustomCommandLine singleLine;
+ singleLine.push_back(cmSystemTools::GetCTestCommand());
+ singleLine.push_back("--force-new-ctest-process");
+ if (cmakeCfgIntDir && *cmakeCfgIntDir && cmakeCfgIntDir[0] != '.') {
+ singleLine.push_back("-C");
+ singleLine.push_back(cmakeCfgIntDir);
+ } else // TODO: This is a hack. Should be something to do with the
+ // generator
+ {
+ singleLine.push_back("$(ARGS)");
+ }
+ gti.CommandLines.push_back(std::move(singleLine));
+ targets.push_back(std::move(gti));
}
void cmGlobalGenerator::AddGlobalTarget_EditCache(
std::vector<GlobalTargetInfo>& targets)
{
const char* editCacheTargetName = this->GetEditCacheTargetName();
- if (editCacheTargetName) {
- GlobalTargetInfo gti;
- gti.Name = editCacheTargetName;
- cmCustomCommandLine singleLine;
-
- // Use generator preference for the edit_cache rule if it is defined.
- std::string edit_cmd = this->GetEditCacheCommand();
- if (!edit_cmd.empty()) {
- singleLine.push_back(edit_cmd);
- singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
- singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
- gti.Message = "Running CMake cache editor...";
- gti.UsesTerminal = true;
- gti.CommandLines.push_back(singleLine);
- } else {
- singleLine.push_back(cmSystemTools::GetCMakeCommand());
- singleLine.push_back("-E");
- singleLine.push_back("echo");
- singleLine.push_back("No interactive CMake dialog available.");
- gti.Message = "No interactive CMake dialog available...";
- gti.UsesTerminal = false;
- gti.CommandLines.push_back(singleLine);
- }
+ if (!editCacheTargetName) {
+ return;
+ }
+ GlobalTargetInfo gti;
+ gti.Name = editCacheTargetName;
+ cmCustomCommandLine singleLine;
- targets.push_back(gti);
+ // Use generator preference for the edit_cache rule if it is defined.
+ std::string edit_cmd = this->GetEditCacheCommand();
+ if (!edit_cmd.empty()) {
+ singleLine.push_back(std::move(edit_cmd));
+ singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
+ singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
+ gti.Message = "Running CMake cache editor...";
+ gti.UsesTerminal = true;
+ } else {
+ singleLine.push_back(cmSystemTools::GetCMakeCommand());
+ singleLine.push_back("-E");
+ singleLine.push_back("echo");
+ singleLine.push_back("No interactive CMake dialog available.");
+ gti.Message = "No interactive CMake dialog available...";
+ gti.UsesTerminal = false;
}
+ gti.CommandLines.push_back(std::move(singleLine));
+
+ targets.push_back(std::move(gti));
}
void cmGlobalGenerator::AddGlobalTarget_RebuildCache(
std::vector<GlobalTargetInfo>& targets)
{
const char* rebuildCacheTargetName = this->GetRebuildCacheTargetName();
- if (rebuildCacheTargetName) {
- GlobalTargetInfo gti;
- gti.Name = rebuildCacheTargetName;
- gti.Message = "Running CMake to regenerate build system...";
- gti.UsesTerminal = true;
- cmCustomCommandLine singleLine;
- singleLine.push_back(cmSystemTools::GetCMakeCommand());
- singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
- singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
- gti.CommandLines.push_back(singleLine);
- targets.push_back(gti);
+ if (!rebuildCacheTargetName) {
+ return;
}
+ GlobalTargetInfo gti;
+ gti.Name = rebuildCacheTargetName;
+ gti.Message = "Running CMake to regenerate build system...";
+ gti.UsesTerminal = true;
+ cmCustomCommandLine singleLine;
+ singleLine.push_back(cmSystemTools::GetCMakeCommand());
+ singleLine.push_back("-H$(CMAKE_SOURCE_DIR)");
+ singleLine.push_back("-B$(CMAKE_BINARY_DIR)");
+ gti.CommandLines.push_back(std::move(singleLine));
+ targets.push_back(std::move(gti));
}
void cmGlobalGenerator::AddGlobalTarget_Install(
@@ -2315,7 +2457,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
gti.Name = "list_install_components";
gti.Message = ostr.str();
gti.UsesTerminal = false;
- targets.push_back(gti);
+ targets.push_back(std::move(gti));
}
std::string cmd = cmSystemTools::GetCMakeCommand();
GlobalTargetInfo gti;
@@ -2369,7 +2511,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
localCmdLine.insert(localCmdLine.begin() + 1,
"-DCMAKE_INSTALL_LOCAL_ONLY=1");
- gti.CommandLines.push_back(localCmdLine);
+ gti.CommandLines.push_back(std::move(localCmdLine));
targets.push_back(gti);
}
@@ -2385,7 +2527,7 @@ void cmGlobalGenerator::AddGlobalTarget_Install(
stripCmdLine.insert(stripCmdLine.begin() + 1,
"-DCMAKE_INSTALL_DO_STRIP=1");
- gti.CommandLines.push_back(stripCmdLine);
+ gti.CommandLines.push_back(std::move(stripCmdLine));
targets.push_back(gti);
}
}
@@ -2467,7 +2609,7 @@ std::string cmGlobalGenerator::GenerateRuleFile(
bool cmGlobalGenerator::ShouldStripResourcePath(cmMakefile* mf) const
{
- return mf->PlatformIsAppleIos();
+ return mf->PlatformIsAppleEmbedded();
}
std::string cmGlobalGenerator::GetSharedLibFlagsForLanguage(
@@ -2503,14 +2645,13 @@ bool cmGlobalGenerator::IsReservedTarget(std::string const& name)
// by one or more of the cmake generators.
// Adding additional targets to this list will require a policy!
- const char* reservedTargets[] = {
- "all", "ALL_BUILD", "help", "install", "INSTALL",
- "preinstall", "clean", "edit_cache", "rebuild_cache", "test",
- "RUN_TESTS", "package", "PACKAGE", "package_source", "ZERO_CHECK"
- };
+ const char* reservedTargets[] = { "all", "ALL_BUILD", "help",
+ "install", "INSTALL", "preinstall",
+ "clean", "edit_cache", "rebuild_cache",
+ "ZERO_CHECK" };
- return std::find(cmArrayBegin(reservedTargets), cmArrayEnd(reservedTargets),
- name) != cmArrayEnd(reservedTargets);
+ return std::find(cm::cbegin(reservedTargets), cm::cend(reservedTargets),
+ name) != cm::cend(reservedTargets);
}
void cmGlobalGenerator::SetExternalMakefileProjectGenerator(
@@ -2713,7 +2854,7 @@ void cmGlobalGenerator::CheckRuleHashes(std::string const& pfile,
// that if the feature is turned back on and the rule has
// changed the file is still rebuilt.
std::string fpath = cmSystemTools::CollapseFullPath(fname, home.c_str());
- if (cmSystemTools::FileExists(fpath.c_str())) {
+ if (cmSystemTools::FileExists(fpath)) {
RuleHash hash;
strncpy(hash.Data, line.c_str(), 32);
this->RuleHashes[fname] = hash;
@@ -2779,7 +2920,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
Json::Value& lj_target_labels = lj_target["labels"] = Json::arrayValue;
Json::Value& lj_sources = lj_root["sources"] = Json::arrayValue;
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
cmGeneratedFileStream fout(file.c_str());
std::vector<std::string> labels;
@@ -2830,7 +2971,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
std::vector<std::string> configs;
target->Target->GetMakefile()->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
for (std::string const& c : configs) {
target->GetSourceFiles(sources, c);
@@ -2925,7 +3066,7 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
std::string path = this->CMakeInstance->GetHomeOutputDirectory();
path += "/CPackProperties.cmake";
- if (!cmSystemTools::FileExists(path.c_str()) && installedFiles.empty()) {
+ if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
return true;
}
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 18ca682c7..34ed5b0e6 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -14,8 +14,8 @@
#include <vector>
#include "cmCustomCommandLines.h"
+#include "cmDuration.h"
#include "cmExportSetMap.h"
-#include "cmQtAutoGenDigest.h"
#include "cmStateSnapshot.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
@@ -33,6 +33,7 @@ class cmLinkLineComputer;
class cmLocalGenerator;
class cmMakefile;
class cmOutputConverter;
+class cmQtAutoGenInitializer;
class cmSourceFile;
class cmStateDirectory;
class cmake;
@@ -70,6 +71,9 @@ public:
/** Tell the generator about the target system. */
virtual bool SetSystemName(std::string const&, cmMakefile*) { return true; }
+ /** Set the generator-specific instance. Returns true if supported. */
+ virtual bool SetGeneratorInstance(std::string const& i, cmMakefile* mf);
+
/** Set the generator-specific platform name. Returns true if platform
is supported and false otherwise. */
virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
@@ -157,11 +161,17 @@ public:
const std::string& projectName, const std::string& targetName,
std::string& output, const std::string& makeProgram,
const std::string& config, bool clean, bool fast, bool verbose,
- double timeout, cmSystemTools::OutputOption outputflag =
- cmSystemTools::OUTPUT_NONE,
+ cmDuration timeout, cmSystemTools::OutputOption outputflag =
+ cmSystemTools::OUTPUT_NONE,
std::vector<std::string> const& nativeOptions =
std::vector<std::string>());
+ /**
+ * Open a generated IDE project given the following information.
+ */
+ virtual bool Open(const std::string& bindir, const std::string& projectName,
+ bool dryRun);
+
virtual void GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& projectDir,
@@ -224,7 +234,7 @@ public:
void EnableInstallTarget();
- int TryCompileTimeout;
+ cmDuration TryCompileTimeout;
bool GetForceUnixPaths() const { return this->ForceUnixPaths; }
bool GetToolSupportsColor() const { return this->ToolSupportsColor; }
@@ -349,6 +359,10 @@ public:
virtual bool IsIPOSupported() const { return false; }
+ /** Return whether the generator can import external visual studio project
+ using INCLUDE_EXTERNAL_MSPROJECT */
+ virtual bool IsIncludeExternalMSProjectSupported() const { return false; }
+
/** Return whether the generator should use EFFECTIVE_PLATFORM_NAME. This is
relevant for mixed macOS and iOS builds. */
virtual bool UseEffectivePlatformName(cmMakefile*) const { return false; }
@@ -424,7 +438,8 @@ protected:
virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const;
// Qt auto generators
- cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets();
+ std::vector<std::unique_ptr<cmQtAutoGenInitializer>>
+ CreateQtAutoGenInitializers();
std::string SelectMakeProgram(const std::string& makeProgram,
const std::string& makeDefault = "") const;
@@ -533,6 +548,8 @@ private:
virtual void ForceLinkerLanguages();
+ bool CheckTargetsForMissingSources() const;
+
void CreateLocalGenerators();
void CheckCompilerIdCompatibility(cmMakefile* mf,
@@ -557,6 +574,9 @@ private:
void ClearGeneratorMembers();
+ bool CheckCMP0037(std::string const& targetName,
+ std::string const& reason) const;
+
void IndexMakefile(cmMakefile* mf);
virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; }
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 788a1798a..946ed80ca 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -447,8 +447,8 @@ void cmGlobalGhsMultiGenerator::UpdateBuildFiles(
this->TargetFolderBuildStreams.find(folderName)) {
this->AddFilesUpToPath(
GetBuildFileStream(), &this->TargetFolderBuildStreams,
- this->GetCMakeInstance()->GetHomeOutputDirectory(), folderName,
- GhsMultiGpj::PROJECT);
+ this->GetCMakeInstance()->GetHomeOutputDirectory().c_str(),
+ folderName, GhsMultiGpj::PROJECT);
}
std::vector<cmsys::String> splitPath = cmSystemTools::SplitString(
cmGhsMultiTargetGenerator::GetRelBuildFileName(tgt));
diff --git a/Source/cmGlobalKdevelopGenerator.cxx b/Source/cmGlobalKdevelopGenerator.cxx
deleted file mode 100644
index b1e630e29..000000000
--- a/Source/cmGlobalKdevelopGenerator.cxx
+++ /dev/null
@@ -1,589 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmGlobalKdevelopGenerator.h"
-
-#include "cmGeneratedFileStream.h"
-#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmSourceFile.h"
-#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cmXMLWriter.h"
-#include "cmake.h"
-
-#include "cmsys/Directory.hxx"
-#include "cmsys/FStream.hxx"
-#include <set>
-#include <string.h>
-#include <utility>
-
-cmGlobalKdevelopGenerator::cmGlobalKdevelopGenerator()
- : cmExternalMakefileProjectGenerator()
-{
-}
-
-cmExternalMakefileProjectGeneratorFactory*
-cmGlobalKdevelopGenerator::GetFactory()
-{
- static cmExternalMakefileProjectGeneratorSimpleFactory<
- cmGlobalKdevelopGenerator>
- factory("KDevelop3", "Generates KDevelop 3 project files.");
-
- if (factory.GetSupportedGlobalGenerators().empty()) {
- factory.AddSupportedGlobalGenerator("Unix Makefiles");
-#ifdef CMAKE_USE_NINJA
- factory.AddSupportedGlobalGenerator("Ninja");
-#endif
-
- factory.Aliases.push_back("KDevelop3");
- }
-
- return &factory;
-}
-
-void cmGlobalKdevelopGenerator::Generate()
-{
- // for each sub project in the project create
- // a kdevelop project
- for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
- std::string outputDir = it.second[0]->GetCurrentBinaryDirectory();
- std::string projectDir = it.second[0]->GetSourceDirectory();
- std::string projectName = it.second[0]->GetProjectName();
- std::string cmakeFilePattern("CMakeLists.txt;*.cmake;");
- std::string fileToOpen;
- const std::vector<cmLocalGenerator*>& lgs = it.second;
- // create the project.kdevelop.filelist file
- if (!this->CreateFilelistFile(lgs, outputDir, projectDir, projectName,
- cmakeFilePattern, fileToOpen)) {
- cmSystemTools::Error("Can not create filelist file");
- return;
- }
- // try to find the name of an executable so we have something to
- // run from kdevelop for now just pick the first executable found
- std::string executable;
- for (cmLocalGenerator* lg : lgs) {
- std::vector<cmGeneratorTarget*> const& targets =
- lg->GetGeneratorTargets();
- for (cmGeneratorTarget* target : targets) {
- if (target->GetType() == cmStateEnums::EXECUTABLE) {
- executable = target->GetLocation("");
- break;
- }
- }
- if (!executable.empty()) {
- break;
- }
- }
-
- // now create a project file
- this->CreateProjectFile(outputDir, projectDir, projectName, executable,
- cmakeFilePattern, fileToOpen);
- }
-}
-
-bool cmGlobalKdevelopGenerator::CreateFilelistFile(
- const std::vector<cmLocalGenerator*>& lgs, const std::string& outputDir,
- const std::string& projectDirIn, const std::string& projectname,
- std::string& cmakeFilePattern, std::string& fileToOpen)
-{
- std::string projectDir = projectDirIn + "/";
- std::string filename = outputDir + "/" + projectname + ".kdevelop.filelist";
-
- std::set<std::string> files;
- std::string tmp;
-
- std::vector<std::string> const& hdrExts =
- this->GlobalGenerator->GetCMakeInstance()->GetHeaderExtensions();
-
- for (cmLocalGenerator* lg : lgs) {
- cmMakefile* makefile = lg->GetMakefile();
- const std::vector<std::string>& listFiles = makefile->GetListFiles();
- for (std::string const& listFile : listFiles) {
- tmp = listFile;
- cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
- // make sure the file is part of this source tree
- if ((tmp[0] != '/') &&
- (strstr(tmp.c_str(), cmake::GetCMakeFilesDirectoryPostSlash()) ==
- nullptr)) {
- files.insert(tmp);
- tmp = cmSystemTools::GetFilenameName(tmp);
- // add all files which dont match the default
- // */CMakeLists.txt;*cmake; to the file pattern
- if ((tmp != "CMakeLists.txt") &&
- (strstr(tmp.c_str(), ".cmake") == nullptr)) {
- cmakeFilePattern += tmp + ";";
- }
- }
- }
-
- // get all sources
- const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
- for (cmGeneratorTarget* gt : targets) {
- std::vector<cmSourceFile*> sources;
- gt->GetSourceFiles(sources, gt->Target->GetMakefile()->GetSafeDefinition(
- "CMAKE_BUILD_TYPE"));
- for (cmSourceFile* sf : sources) {
- tmp = sf->GetFullPath();
- std::string headerBasename = cmSystemTools::GetFilenamePath(tmp);
- headerBasename += "/";
- headerBasename += cmSystemTools::GetFilenameWithoutExtension(tmp);
-
- cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
-
- if ((tmp[0] != '/') &&
- (strstr(tmp.c_str(), cmake::GetCMakeFilesDirectoryPostSlash()) ==
- nullptr) &&
- (cmSystemTools::GetFilenameExtension(tmp) != ".moc")) {
- files.insert(tmp);
-
- // check if there's a matching header around
- for (std::string const& hdrExt : hdrExts) {
- std::string hname = headerBasename;
- hname += ".";
- hname += hdrExt;
- if (cmSystemTools::FileExists(hname.c_str())) {
- cmSystemTools::ReplaceString(hname, projectDir.c_str(), "");
- files.insert(hname);
- break;
- }
- }
- }
- }
- for (std::string const& listFile : listFiles) {
- tmp = listFile;
- cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
- if ((tmp[0] != '/') &&
- (strstr(tmp.c_str(), cmake::GetCMakeFilesDirectoryPostSlash()) ==
- nullptr)) {
- files.insert(tmp);
- }
- }
- }
- }
-
- // check if the output file already exists and read it
- // insert all files which exist into the set of files
- cmsys::ifstream oldFilelist(filename.c_str());
- if (oldFilelist) {
- while (cmSystemTools::GetLineFromStream(oldFilelist, tmp)) {
- if (tmp[0] == '/') {
- continue;
- }
- std::string completePath = projectDir + tmp;
- if (cmSystemTools::FileExists(completePath.c_str())) {
- files.insert(tmp);
- }
- }
- oldFilelist.close();
- }
-
- // now write the new filename
- cmGeneratedFileStream fout(filename.c_str());
- if (!fout) {
- return false;
- }
-
- fileToOpen = "";
- for (std::string const& file : files) {
- // get the full path to the file
- tmp = cmSystemTools::CollapseFullPath(file, projectDir.c_str());
- // just select the first source file
- if (fileToOpen.empty()) {
- std::string ext = cmSystemTools::GetFilenameExtension(tmp);
- if ((ext == ".c") || (ext == ".cc") || (ext == ".cpp") ||
- (ext == ".cxx") || (ext == ".C") || (ext == ".h") ||
- (ext == ".hpp")) {
- fileToOpen = tmp;
- }
- }
- // make it relative to the project dir
- cmSystemTools::ReplaceString(tmp, projectDir.c_str(), "");
- // only put relative paths
- if (!tmp.empty() && tmp[0] != '/') {
- fout << tmp << "\n";
- }
- }
- return true;
-}
-
-/* create the project file, if it already exists, merge it with the
-existing one, otherwise create a new one */
-void cmGlobalKdevelopGenerator::CreateProjectFile(
- const std::string& outputDir, const std::string& projectDir,
- const std::string& projectname, const std::string& executable,
- const std::string& cmakeFilePattern, const std::string& fileToOpen)
-{
- this->Blacklist.clear();
-
- std::string filename = outputDir + "/";
- filename += projectname + ".kdevelop";
- std::string sessionFilename = outputDir + "/";
- sessionFilename += projectname + ".kdevses";
-
- if (cmSystemTools::FileExists(filename.c_str())) {
- this->MergeProjectFiles(outputDir, projectDir, filename, executable,
- cmakeFilePattern, fileToOpen, sessionFilename);
- } else {
- // add all subdirectories which are cmake build directories to the
- // kdevelop blacklist so they are not monitored for added or removed files
- // since this is handled by adding files to the cmake files
- cmsys::Directory d;
- if (d.Load(projectDir)) {
- size_t numf = d.GetNumberOfFiles();
- for (unsigned int i = 0; i < numf; i++) {
- std::string nextFile = d.GetFile(i);
- if ((nextFile != ".") && (nextFile != "..")) {
- std::string tmp = projectDir;
- tmp += "/";
- tmp += nextFile;
- if (cmSystemTools::FileIsDirectory(tmp)) {
- tmp += "/CMakeCache.txt";
- if ((nextFile == "CMakeFiles") ||
- (cmSystemTools::FileExists(tmp.c_str()))) {
- this->Blacklist.push_back(nextFile);
- }
- }
- }
- }
- }
- this->CreateNewProjectFile(outputDir, projectDir, filename, executable,
- cmakeFilePattern, fileToOpen, sessionFilename);
- }
-}
-
-void cmGlobalKdevelopGenerator::MergeProjectFiles(
- const std::string& outputDir, const std::string& projectDir,
- const std::string& filename, const std::string& executable,
- const std::string& cmakeFilePattern, const std::string& fileToOpen,
- const std::string& sessionFilename)
-{
- cmsys::ifstream oldProjectFile(filename.c_str());
- if (!oldProjectFile) {
- this->CreateNewProjectFile(outputDir, projectDir, filename, executable,
- cmakeFilePattern, fileToOpen, sessionFilename);
- return;
- }
-
- /* Read the existing project file (line by line), copy all lines
- into the new project file, except the ones which can be reliably
- set from contents of the CMakeLists.txt */
- std::string tmp;
- std::vector<std::string> lines;
- while (cmSystemTools::GetLineFromStream(oldProjectFile, tmp)) {
- lines.push_back(tmp);
- }
- oldProjectFile.close();
-
- cmGeneratedFileStream fout(filename.c_str());
- if (!fout) {
- return;
- }
-
- for (std::string const& l : lines) {
- const char* line = l.c_str();
- // skip these tags as they are always replaced
- if ((strstr(line, "<projectdirectory>") != nullptr) ||
- (strstr(line, "<projectmanagement>") != nullptr) ||
- (strstr(line, "<absoluteprojectpath>") != nullptr) ||
- (strstr(line, "<filelistdirectory>") != nullptr) ||
- (strstr(line, "<buildtool>") != nullptr) ||
- (strstr(line, "<builddir>") != nullptr)) {
- continue;
- }
-
- // output the line from the file if it is not one of the above tags
- fout << l << "\n";
- // if this is the <general> tag output the stuff that goes in the
- // general tag
- if (strstr(line, "<general>")) {
- fout << " <projectmanagement>KDevCustomProject</projectmanagement>\n";
- fout << " <projectdirectory>" << projectDir
- << "</projectdirectory>\n"; // this one is important
- fout << " <absoluteprojectpath>true</absoluteprojectpath>\n";
- // and this one
- }
- // inside kdevcustomproject the <filelistdirectory> must be put
- if (strstr(line, "<kdevcustomproject>")) {
- fout << " <filelistdirectory>" << outputDir
- << "</filelistdirectory>\n";
- }
- // buildtool and builddir go inside <build>
- if (strstr(line, "<build>")) {
- fout << " <buildtool>make</buildtool>\n";
- fout << " <builddir>" << outputDir << "</builddir>\n";
- }
- }
-}
-
-void cmGlobalKdevelopGenerator::CreateNewProjectFile(
- const std::string& outputDir, const std::string& projectDir,
- const std::string& filename, const std::string& executable,
- const std::string& cmakeFilePattern, const std::string& fileToOpen,
- const std::string& sessionFilename)
-{
- cmGeneratedFileStream fout(filename.c_str());
- if (!fout) {
- return;
- }
- cmXMLWriter xml(fout);
-
- // check for a version control system
- bool hasSvn = cmSystemTools::FileExists((projectDir + "/.svn").c_str());
- bool hasCvs = cmSystemTools::FileExists((projectDir + "/CVS").c_str());
-
- bool enableCxx = (this->GlobalGenerator->GetLanguageEnabled("C") ||
- this->GlobalGenerator->GetLanguageEnabled("CXX"));
- bool enableFortran = this->GlobalGenerator->GetLanguageEnabled("Fortran");
- std::string primaryLanguage = "C++";
- if (enableFortran && !enableCxx) {
- primaryLanguage = "Fortran77";
- }
-
- xml.StartDocument();
- xml.StartElement("kdevelop");
- xml.StartElement("general");
-
- xml.Element("author", "");
- xml.Element("email", "");
- xml.Element("version", "$VERSION$");
- xml.Element("projectmanagement", "KDevCustomProject");
- xml.Element("primarylanguage", primaryLanguage);
- xml.Element("ignoreparts");
- xml.Element("projectdirectory", projectDir); // this one is important
- xml.Element("absoluteprojectpath", "true"); // and this one
-
- // setup additional languages
- xml.StartElement("secondaryLanguages");
- if (enableFortran && enableCxx) {
- xml.Element("language", "Fortran");
- }
- if (enableCxx) {
- xml.Element("language", "C");
- }
- xml.EndElement();
-
- if (hasSvn) {
- xml.Element("versioncontrol", "kdevsubversion");
- } else if (hasCvs) {
- xml.Element("versioncontrol", "kdevcvsservice");
- }
-
- xml.EndElement(); // general
- xml.StartElement("kdevcustomproject");
-
- xml.Element("filelistdirectory", outputDir);
-
- xml.StartElement("run");
- xml.Element("mainprogram", executable);
- xml.Element("directoryradio", "custom");
- xml.Element("customdirectory", outputDir);
- xml.Element("programargs", "");
- xml.Element("terminal", "false");
- xml.Element("autocompile", "true");
- xml.Element("envvars");
- xml.EndElement();
-
- xml.StartElement("build");
- xml.Element("buildtool", "make"); // this one is important
- xml.Element("builddir", outputDir); // and this one
- xml.EndElement();
-
- xml.StartElement("make");
- xml.Element("abortonerror", "false");
- xml.Element("numberofjobs", 1);
- xml.Element("dontact", "false");
- xml.Element("makebin", this->GlobalGenerator->GetLocalGenerators()[0]
- ->GetMakefile()
- ->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"));
- xml.Element("selectedenvironment", "default");
-
- xml.StartElement("environments");
- xml.StartElement("default");
-
- xml.StartElement("envvar");
- xml.Attribute("value", 1);
- xml.Attribute("name", "VERBOSE");
- xml.EndElement();
-
- xml.StartElement("envvar");
- xml.Attribute("value", 1);
- xml.Attribute("name", "CMAKE_NO_VERBOSE");
- xml.EndElement();
-
- xml.EndElement(); // default
- xml.EndElement(); // environments
- xml.EndElement(); // make
-
- xml.StartElement("blacklist");
- for (std::string const& dir : this->Blacklist) {
- xml.Element("path", dir);
- }
- xml.EndElement();
-
- xml.EndElement(); // kdevcustomproject
-
- xml.StartElement("kdevfilecreate");
- xml.Element("filetypes");
- xml.StartElement("useglobaltypes");
-
- xml.StartElement("type");
- xml.Attribute("ext", "ui");
- xml.EndElement();
-
- xml.StartElement("type");
- xml.Attribute("ext", "cpp");
- xml.EndElement();
-
- xml.StartElement("type");
- xml.Attribute("ext", "h");
- xml.EndElement();
-
- xml.EndElement(); // useglobaltypes
- xml.EndElement(); // kdevfilecreate
-
- xml.StartElement("kdevdoctreeview");
- xml.StartElement("projectdoc");
- xml.Element("userdocDir", "html/");
- xml.Element("apidocDir", "html/");
- xml.EndElement(); // projectdoc
- xml.Element("ignoreqt_xml");
- xml.Element("ignoredoxygen");
- xml.Element("ignorekdocs");
- xml.Element("ignoretocs");
- xml.Element("ignoredevhelp");
- xml.EndElement(); // kdevdoctreeview;
-
- if (enableCxx) {
- xml.StartElement("cppsupportpart");
- xml.StartElement("filetemplates");
- xml.Element("interfacesuffix", ".h");
- xml.Element("implementationsuffix", ".cpp");
- xml.EndElement(); // filetemplates
- xml.EndElement(); // cppsupportpart
-
- xml.StartElement("kdevcppsupport");
- xml.StartElement("codecompletion");
- xml.Element("includeGlobalFunctions", "true");
- xml.Element("includeTypes", "true");
- xml.Element("includeEnums", "true");
- xml.Element("includeTypedefs", "false");
- xml.Element("automaticCodeCompletion", "true");
- xml.Element("automaticArgumentsHint", "true");
- xml.Element("automaticHeaderCompletion", "true");
- xml.Element("codeCompletionDelay", 250);
- xml.Element("argumentsHintDelay", 400);
- xml.Element("headerCompletionDelay", 250);
- xml.EndElement(); // codecompletion
- xml.Element("references");
- xml.EndElement(); // kdevcppsupport;
- }
-
- if (enableFortran) {
- xml.StartElement("kdevfortransupport");
- xml.StartElement("ftnchek");
- xml.Element("division", "false");
- xml.Element("extern", "false");
- xml.Element("declare", "false");
- xml.Element("pure", "false");
- xml.Element("argumentsall", "false");
- xml.Element("commonall", "false");
- xml.Element("truncationall", "false");
- xml.Element("usageall", "false");
- xml.Element("f77all", "false");
- xml.Element("portabilityall", "false");
- xml.Element("argumentsonly");
- xml.Element("commononly");
- xml.Element("truncationonly");
- xml.Element("usageonly");
- xml.Element("f77only");
- xml.Element("portabilityonly");
- xml.EndElement(); // ftnchek
- xml.EndElement(); // kdevfortransupport;
- }
-
- // set up file groups. maybe this can be used with the CMake SOURCE_GROUP()
- // command
- xml.StartElement("kdevfileview");
- xml.StartElement("groups");
-
- xml.StartElement("group");
- xml.Attribute("pattern", cmakeFilePattern);
- xml.Attribute("name", "CMake");
- xml.EndElement();
-
- if (enableCxx) {
- xml.StartElement("group");
- xml.Attribute("pattern", "*.h;*.hxx;*.hpp");
- xml.Attribute("name", "Header");
- xml.EndElement();
-
- xml.StartElement("group");
- xml.Attribute("pattern", "*.c");
- xml.Attribute("name", "C Sources");
- xml.EndElement();
-
- xml.StartElement("group");
- xml.Attribute("pattern", "*.cpp;*.C;*.cxx;*.cc");
- xml.Attribute("name", "C++ Sources");
- xml.EndElement();
- }
-
- if (enableFortran) {
- xml.StartElement("group");
- xml.Attribute("pattern",
- "*.f;*.F;*.f77;*.F77;*.f90;*.F90;*.for;*.f95;*.F95");
- xml.Attribute("name", "Fortran Sources");
- xml.EndElement();
- }
-
- xml.StartElement("group");
- xml.Attribute("pattern", "*.ui");
- xml.Attribute("name", "Qt Designer files");
- xml.EndElement();
-
- xml.Element("hidenonprojectfiles", "true");
- xml.EndElement(); // groups
-
- xml.StartElement("tree");
- xml.Element("hidepatterns", "*.o,*.lo,CVS,*~,cmake*");
- xml.Element("hidenonprojectfiles", "true");
- xml.EndElement(); // tree
-
- xml.EndElement(); // kdevfileview
- xml.EndElement(); // kdevelop;
- xml.EndDocument();
-
- if (sessionFilename.empty()) {
- return;
- }
-
- // and a session file, so that kdevelop opens a file if it opens the
- // project the first time
- cmGeneratedFileStream devses(sessionFilename.c_str());
- if (!devses) {
- return;
- }
- cmXMLWriter sesxml(devses);
- sesxml.StartDocument("UTF-8");
- sesxml.Doctype("KDevPrjSession");
- sesxml.StartElement("KDevPrjSession");
-
- sesxml.StartElement("DocsAndViews");
- sesxml.Attribute("NumberOfDocuments", 1);
-
- sesxml.StartElement("Doc0");
- sesxml.Attribute("NumberOfViews", 1);
- sesxml.Attribute("URL", "file://" + fileToOpen);
-
- sesxml.StartElement("View0");
- sesxml.Attribute("line", 0);
- sesxml.Attribute("Type", "Source");
- sesxml.EndElement(); // View0
-
- sesxml.EndElement(); // Doc0
- sesxml.EndElement(); // DocsAndViews
- sesxml.EndElement(); // KDevPrjSession;
-}
diff --git a/Source/cmGlobalKdevelopGenerator.h b/Source/cmGlobalKdevelopGenerator.h
deleted file mode 100644
index d6c43f3f9..000000000
--- a/Source/cmGlobalKdevelopGenerator.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmGlobalKdevelopGenerator_h
-#define cmGlobalKdevelopGenerator_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include "cmExternalMakefileProjectGenerator.h"
-
-#include <string>
-#include <vector>
-
-class cmLocalGenerator;
-
-/** \class cmGlobalKdevelopGenerator
- * \brief Write Unix Makefiles accompanied by KDevelop3 project files.
- *
- * cmGlobalKdevelopGenerator produces a project file for KDevelop 3 (KDevelop
- * > 3.1.1). The project is based on the "Custom Makefile based C/C++"
- * project of KDevelop. Such a project consists of Unix Makefiles in the
- * build directory together with a \<your_project\>.kdevelop project file,
- * which contains the project settings and a \<your_project\>.kdevelop.filelist
- * file, which lists the source files relative to the kdevelop project
- * directory. The kdevelop project directory is the base source directory.
- */
-class cmGlobalKdevelopGenerator : public cmExternalMakefileProjectGenerator
-{
-public:
- cmGlobalKdevelopGenerator();
-
- static cmExternalMakefileProjectGeneratorFactory* GetFactory();
-
- void Generate() override;
-
-private:
- /*** Create the foo.kdevelop.filelist file, return false if it doesn't
- succeed. If the file already exists the contents will be merged.
- */
- bool CreateFilelistFile(const std::vector<cmLocalGenerator*>& lgs,
- const std::string& outputDir,
- const std::string& projectDirIn,
- const std::string& projectname,
- std::string& cmakeFilePattern,
- std::string& fileToOpen);
-
- /** Create the foo.kdevelop file. This one calls MergeProjectFiles()
- if it already exists, otherwise createNewProjectFile() The project
- files will be created in \a outputDir (in the build tree), the
- kdevelop project dir will be set to \a projectDir (in the source
- tree). \a cmakeFilePattern consists of a lists of all cmake
- listfiles used by this CMakeLists.txt */
- void CreateProjectFile(const std::string& outputDir,
- const std::string& projectDir,
- const std::string& projectname,
- const std::string& executable,
- const std::string& cmakeFilePattern,
- const std::string& fileToOpen);
-
- /*** Reads the old foo.kdevelop line by line and only replaces the
- "important" lines
- */
- void MergeProjectFiles(const std::string& outputDir,
- const std::string& projectDir,
- const std::string& filename,
- const std::string& executable,
- const std::string& cmakeFilePattern,
- const std::string& fileToOpen,
- const std::string& sessionFilename);
- ///! Creates a new foo.kdevelop and a new foo.kdevses file
- void CreateNewProjectFile(const std::string& outputDir,
- const std::string& projectDir,
- const std::string& filename,
- const std::string& executable,
- const std::string& cmakeFilePattern,
- const std::string& fileToOpen,
- const std::string& sessionFilename);
-
- std::vector<std::string> Blacklist;
-};
-
-#endif
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index d5531cbe8..b251f86a7 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -8,7 +8,6 @@
#include "cmsys/FStream.hxx"
#include <algorithm>
#include <ctype.h>
-#include <functional>
#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
@@ -114,7 +113,7 @@ std::string cmGlobalNinjaGenerator::EncodeIdent(const std::string& ident,
std::ostream& vars)
{
if (std::find_if(ident.begin(), ident.end(),
- std::not1(std::ptr_fun(IsIdentChar))) != ident.end()) {
+ [](char c) { return !IsIdentChar(c); }) != ident.end()) {
static unsigned VarNum = 0;
std::ostringstream names;
names << "ident" << VarNum++;
@@ -871,7 +870,7 @@ std::string const& cmGlobalNinjaGenerator::ConvertToNinjaPath(
cmLocalNinjaGenerator* ng =
static_cast<cmLocalNinjaGenerator*>(this->LocalGenerators[0]);
- const char* bin_dir = ng->GetState()->GetBinaryDirectory();
+ std::string const& bin_dir = ng->GetState()->GetBinaryDirectory();
std::string convPath = ng->ConvertToRelativePath(bin_dir, path);
convPath = this->NinjaOutputPath(convPath);
#ifdef _WIN32
@@ -903,7 +902,7 @@ void cmGlobalNinjaGenerator::AddCXXCompileCommand(
}
std::string sourceFileName = sourceFile;
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
sourceFileName = cmSystemTools::CollapseFullPath(
sourceFileName, this->GetCMakeInstance()->GetHomeOutputDirectory());
}
@@ -1728,7 +1727,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile(
info.Requires.push_back(ddi_require.asString());
}
}
- objects.push_back(info);
+ objects.push_back(std::move(info));
}
// Map from module name to module file path, if known.
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index be4012680..d990a6c02 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -21,7 +21,6 @@
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
-#include "cmTarget.h"
#include "cmTargetDepend.h"
#include "cmake.h"
@@ -421,7 +420,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
std::string tname = lg->GetRelativeTargetDirectory(gtarget);
tname += "/";
tname += pass;
- depends.push_back(tname);
+ depends.push_back(std::move(tname));
}
}
}
@@ -433,7 +432,7 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
std::string subdir = c.GetDirectory().GetCurrentBinary();
subdir += "/";
subdir += pass;
- depends.push_back(subdir);
+ depends.push_back(std::move(subdir));
}
// Work-around for makes that drop rules that have no dependencies
@@ -460,10 +459,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRules2(
}
// Begin the directory-level rules section.
- std::string dir = cmSystemTools::ConvertToOutputPath(
- lg->ConvertToRelativePath(lg->GetBinaryDirectory(),
- lg->GetCurrentBinaryDirectory())
- .c_str());
+ std::string dir =
+ cmSystemTools::ConvertToOutputPath(lg->ConvertToRelativePath(
+ lg->GetBinaryDirectory(), lg->GetCurrentBinaryDirectory()));
lg->WriteDivider(ruleFileStream);
ruleFileStream << "# Directory level rules for directory " << dir << "\n\n";
@@ -514,7 +512,7 @@ void cmGlobalUnixMakefileGenerator3::GenerateBuildCommand(
tname =
conv.ConvertToRelativePath(mf->GetState()->GetBinaryDirectory(), tname);
cmSystemTools::ConvertToOutputSlashes(tname);
- makeCommand.push_back(tname);
+ makeCommand.push_back(std::move(tname));
if (this->Makefiles.empty()) {
delete mf;
}
@@ -630,8 +628,6 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
makefileName = localName;
makefileName += "/build.make";
- bool needRequiresStep = this->NeedRequiresStep(gtarget);
-
lg->WriteDivider(ruleFileStream);
ruleFileStream << "# Target rules for target " << localName << "\n\n";
@@ -641,13 +637,6 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
commands.push_back(
lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
- // add requires if we need it for this generator
- if (needRequiresStep) {
- makeTargetName = localName;
- makeTargetName += "/requires";
- commands.push_back(
- lg->GetRecursiveMakeCall(makefileName.c_str(), makeTargetName));
- }
makeTargetName = localName;
makeTargetName += "/build";
commands.push_back(
@@ -952,21 +941,3 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
commands, true);
ruleFileStream << "\n\n";
}
-
-bool cmGlobalUnixMakefileGenerator3::NeedRequiresStep(
- const cmGeneratorTarget* target)
-{
- std::set<std::string> languages;
- target->GetLanguages(
- languages,
- target->Target->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
- for (std::string const& l : languages) {
- std::string var = "CMAKE_NEEDS_REQUIRES_STEP_";
- var += l;
- var += "_FLAG";
- if (target->Target->GetMakefile()->GetDefinition(var)) {
- return true;
- }
- }
- return false;
-}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index d601f8845..f9ce88cb4 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -174,9 +174,6 @@ protected:
void AppendGlobalTargetDepends(std::vector<std::string>& depends,
cmGeneratorTarget* target);
- // does this generator need a requires step for any of its targets
- bool NeedRequiresStep(cmGeneratorTarget const*);
-
// Target name hooks for superclass.
const char* GetAllTargetName() const override { return "all"; }
const char* GetInstallTargetName() const override { return "install"; }
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 8c9e4616e..73a5daec2 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -478,12 +478,11 @@ void cmGlobalVisualStudio10Generator::Generate()
void cmGlobalVisualStudio10Generator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
- for (std::vector<std::string>::const_iterator it = lang.begin();
- it != lang.end(); ++it) {
- if (*it == "ASM_NASM") {
+ for (std::string const& it : lang) {
+ if (it == "ASM_NASM") {
this->NasmEnabled = true;
}
- if (*it == "CUDA") {
+ if (it == "CUDA") {
this->CudaEnabled = true;
}
}
@@ -829,8 +828,9 @@ void cmGlobalVisualStudio10Generator::GenerateBuildCommand(
if (parser.ParseFile(slnFile, slnData,
cmVisualStudioSlnParser::DataGroupProjects)) {
std::vector<cmSlnProjectEntry> slnProjects = slnData.GetProjects();
- for (std::vector<cmSlnProjectEntry>::iterator i = slnProjects.begin();
- !useDevEnv && i != slnProjects.end(); ++i) {
+ for (std::vector<cmSlnProjectEntry>::const_iterator i =
+ slnProjects.cbegin();
+ !useDevEnv && i != slnProjects.cend(); ++i) {
std::string proj = i->GetRelativePath();
if (proj.size() > 7 && proj.substr(proj.size() - 7) == ".vfproj") {
useDevEnv = true;
@@ -951,6 +951,11 @@ void cmGlobalVisualStudio10Generator::PathTooLong(cmGeneratorTarget* target,
}
}
+std::string cmGlobalVisualStudio10Generator::Encoding()
+{
+ return "utf-8";
+}
+
bool cmGlobalVisualStudio10Generator::IsNsightTegra() const
{
return !this->NsightTegraVersion.empty();
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 5f80c7342..f2501c222 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -18,29 +18,31 @@ public:
const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual bool SetSystemName(std::string const& s, cmMakefile* mf);
- virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
- virtual bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf);
+ bool SetSystemName(std::string const& s, cmMakefile* mf) override;
+ bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
+ bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
- virtual void GenerateBuildCommand(
- std::vector<std::string>& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
- std::vector<std::string> const& makeOptions = std::vector<std::string>());
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ const std::string& projectName,
+ const std::string& projectDir,
+ const std::string& targetName,
+ const std::string& config, bool fast, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
///! create the correct local generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
/**
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
- virtual void WriteSLNHeader(std::ostream& fout);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
+ void WriteSLNHeader(std::ostream& fout) override;
bool IsCudaEnabled() const { return this->CudaEnabled; }
@@ -87,15 +89,16 @@ public:
/** Return true if building for WindowsStore */
bool TargetsWindowsStore() const { return this->SystemIsWindowsStore; }
- virtual const char* GetCMakeCFGIntDir() const { return "$(Configuration)"; }
+ const char* GetCMakeCFGIntDir() const override { return "$(Configuration)"; }
bool Find64BitTools(cmMakefile* mf);
/** Generate an <output>.rule file path for a given command output. */
- virtual std::string GenerateRuleFile(std::string const& output) const;
+ std::string GenerateRuleFile(std::string const& output) const override;
void PathTooLong(cmGeneratorTarget* target, cmSourceFile const* sf,
std::string const& sfRel);
+ std::string Encoding() override;
virtual const char* GetToolsVersion() { return "4.0"; }
bool FindMakeProgram(cmMakefile* mf) override;
@@ -113,7 +116,7 @@ public:
cmIDEFlagTable const* GetNasmFlagTable() const;
protected:
- virtual void Generate();
+ void Generate() override;
virtual bool InitializeSystem(cmMakefile* mf);
virtual bool InitializeWindows(cmMakefile* mf);
virtual bool InitializeWindowsCE(cmMakefile* mf);
@@ -127,7 +130,7 @@ protected:
virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
- virtual const char* GetIDEVersion() { return "10.0"; }
+ const char* GetIDEVersion() override { return "10.0"; }
std::string const& GetMSBuildCommand();
@@ -173,8 +176,8 @@ private:
bool MSBuildCommandInitialized;
cmVisualStudio10ToolsetOptions ToolsetOptions;
virtual std::string FindMSBuildCommand();
- virtual std::string FindDevEnvCommand();
- virtual std::string GetVSMakeProgram() { return this->GetMSBuildCommand(); }
+ std::string FindDevEnvCommand() override;
+ std::string GetVSMakeProgram() override { return this->GetMSBuildCommand(); }
bool PlatformToolsetNeedsDebugEnum;
@@ -186,6 +189,6 @@ private:
bool CudaEnabled;
// We do not use the reload macros for VS >= 10.
- virtual std::string GetUserMacrosDirectory() { return ""; }
+ std::string GetUserMacrosDirectory() override { return ""; }
};
#endif
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index cb3b0477f..f1d5a8c64 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -83,9 +83,8 @@ public:
std::set<std::string> installedSDKs =
cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs();
- for (std::set<std::string>::const_iterator i = installedSDKs.begin();
- i != installedSDKs.end(); ++i) {
- names.push_back(std::string(vs11generatorName) + " " + *i);
+ for (std::string const& i : installedSDKs) {
+ names.push_back(std::string(vs11generatorName) + " " + i);
}
}
@@ -224,18 +223,17 @@ cmGlobalVisualStudio11Generator::GetInstalledWindowsCESDKs()
cmSystemTools::KeyWOW64_32);
std::set<std::string> ret;
- for (std::vector<std::string>::const_iterator i = subkeys.begin();
- i != subkeys.end(); ++i) {
+ for (std::string const& i : subkeys) {
std::string key = sdksKey;
key += '\\';
- key += *i;
+ key += i;
key += ';';
std::string path;
- if (cmSystemTools::ReadRegistryValue(key.c_str(), path,
+ if (cmSystemTools::ReadRegistryValue(key, path,
cmSystemTools::KeyWOW64_32) &&
!path.empty()) {
- ret.insert(*i);
+ ret.insert(i);
}
}
diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h
index 8b75aadbf..40f02fb12 100644
--- a/Source/cmGlobalVisualStudio11Generator.h
+++ b/Source/cmGlobalVisualStudio11Generator.h
@@ -24,15 +24,15 @@ public:
const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual void WriteSLNHeader(std::ostream& fout);
+ void WriteSLNHeader(std::ostream& fout) override;
protected:
- virtual bool InitializeWindowsPhone(cmMakefile* mf);
- virtual bool InitializeWindowsStore(cmMakefile* mf);
- virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ bool InitializeWindowsPhone(cmMakefile* mf) override;
+ bool InitializeWindowsStore(cmMakefile* mf) override;
+ bool SelectWindowsPhoneToolset(std::string& toolset) const override;
+ bool SelectWindowsStoreToolset(std::string& toolset) const override;
// Used to verify that the Desktop toolset for the current generator is
// installed on the machine.
@@ -43,12 +43,12 @@ protected:
bool IsWindowsPhoneToolsetInstalled() const;
bool IsWindowsStoreToolsetInstalled() const;
- virtual const char* GetIDEVersion() { return "11.0"; }
+ const char* GetIDEVersion() override { return "11.0"; }
bool UseFolderProperty();
static std::set<std::string> GetInstalledWindowsCESDKs();
/** Return true if the configuration needs to be deployed */
- virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
+ bool NeedsDeploy(cmStateEnums::TargetType type) const override;
private:
class Factory;
diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h
index 5ba21a662..c941809ff 100644
--- a/Source/cmGlobalVisualStudio12Generator.h
+++ b/Source/cmGlobalVisualStudio12Generator.h
@@ -22,32 +22,32 @@ public:
const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual void WriteSLNHeader(std::ostream& fout);
+ void WriteSLNHeader(std::ostream& fout) override;
// in Visual Studio 2013 they detached the MSBuild tools version
// from the .Net Framework version and instead made it have it's own
// version number
- virtual const char* GetToolsVersion() { return "12.0"; }
+ const char* GetToolsVersion() override { return "12.0"; }
protected:
bool ProcessGeneratorToolsetField(std::string const& key,
std::string const& value) override;
- virtual bool InitializeWindowsPhone(cmMakefile* mf);
- virtual bool InitializeWindowsStore(cmMakefile* mf);
- virtual bool SelectWindowsPhoneToolset(std::string& toolset) const;
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ bool InitializeWindowsPhone(cmMakefile* mf) override;
+ bool InitializeWindowsStore(cmMakefile* mf) override;
+ bool SelectWindowsPhoneToolset(std::string& toolset) const override;
+ bool SelectWindowsStoreToolset(std::string& toolset) const override;
// Used to verify that the Desktop toolset for the current generator is
// installed on the machine.
- virtual bool IsWindowsDesktopToolsetInstalled() const;
+ bool IsWindowsDesktopToolsetInstalled() const override;
// These aren't virtual because we need to check if the selected version
// of the toolset is installed
bool IsWindowsPhoneToolsetInstalled() const;
bool IsWindowsStoreToolsetInstalled() const;
- virtual const char* GetIDEVersion() { return "12.0"; }
+ const char* GetIDEVersion() override { return "12.0"; }
private:
class Factory;
};
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index 97d531378..c440e0de6 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -257,9 +257,8 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
std::vector<std::string> sdks;
// Grab the paths of the different SDKs that are installed
- for (std::vector<std::string>::iterator i = win10Roots.begin();
- i != win10Roots.end(); ++i) {
- std::string path = *i + "/Include/*";
+ for (std::string const& i : win10Roots) {
+ std::string path = i + "/Include/*";
cmSystemTools::GlobDirs(path, sdks);
}
@@ -269,19 +268,17 @@ std::string cmGlobalVisualStudio14Generator::GetWindows10SDKVersion()
if (!sdks.empty()) {
// Only use the filename, which will be the SDK version.
- for (std::vector<std::string>::iterator i = sdks.begin(); i != sdks.end();
- ++i) {
- *i = cmSystemTools::GetFilenameName(*i);
+ for (std::string& i : sdks) {
+ i = cmSystemTools::GetFilenameName(i);
}
// Sort the results to make sure we select the most recent one.
std::sort(sdks.begin(), sdks.end(), cmSystemTools::VersionCompareGreater);
// Look for a SDK exactly matching the requested target version.
- for (std::vector<std::string>::iterator i = sdks.begin(); i != sdks.end();
- ++i) {
- if (cmSystemTools::VersionCompareEqual(*i, this->SystemVersion)) {
- return *i;
+ for (std::string const& i : sdks) {
+ if (cmSystemTools::VersionCompareEqual(i, this->SystemVersion)) {
+ return i;
}
}
diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h
index 425fb227f..d92a11a18 100644
--- a/Source/cmGlobalVisualStudio14Generator.h
+++ b/Source/cmGlobalVisualStudio14Generator.h
@@ -22,26 +22,26 @@ public:
const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual void WriteSLNHeader(std::ostream& fout);
+ void WriteSLNHeader(std::ostream& fout) override;
- virtual const char* GetToolsVersion() { return "14.0"; }
+ const char* GetToolsVersion() override { return "14.0"; }
protected:
- virtual bool InitializeWindows(cmMakefile* mf);
- virtual bool InitializeWindowsStore(cmMakefile* mf);
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ bool InitializeWindows(cmMakefile* mf) override;
+ bool InitializeWindowsStore(cmMakefile* mf) override;
+ bool SelectWindowsStoreToolset(std::string& toolset) const override;
// These aren't virtual because we need to check if the selected version
// of the toolset is installed
bool IsWindowsStoreToolsetInstalled() const;
- virtual const char* GetIDEVersion() { return "14.0"; }
+ const char* GetIDEVersion() override { return "14.0"; }
virtual bool SelectWindows10SDK(cmMakefile* mf, bool required);
// Used to verify that the Desktop toolset for the current generator is
// installed on the machine.
- virtual bool IsWindowsDesktopToolsetInstalled() const;
+ bool IsWindowsDesktopToolsetInstalled() const override;
std::string GetWindows10SDKVersion();
diff --git a/Source/cmGlobalVisualStudio15Generator.cxx b/Source/cmGlobalVisualStudio15Generator.cxx
index d2bf7cca6..014d93d94 100644
--- a/Source/cmGlobalVisualStudio15Generator.cxx
+++ b/Source/cmGlobalVisualStudio15Generator.cxx
@@ -111,6 +111,53 @@ void cmGlobalVisualStudio15Generator::WriteSLNHeader(std::ostream& fout)
}
}
+bool cmGlobalVisualStudio15Generator::SetGeneratorInstance(
+ std::string const& i, cmMakefile* mf)
+{
+ if (!i.empty()) {
+ if (!this->vsSetupAPIHelper.SetVSInstance(i)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "could not find specified instance of Visual Studio:\n"
+ " " << i;
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+ }
+
+ std::string vsInstance;
+ if (!this->vsSetupAPIHelper.GetVSInstanceInfo(vsInstance)) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Generator\n"
+ " " << this->GetName() << "\n"
+ "could not find any instance of Visual Studio.\n";
+ /* clang-format on */
+ mf->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return false;
+ }
+
+ // Save the selected instance persistently.
+ std::string genInstance = mf->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE");
+ if (vsInstance != genInstance) {
+ this->CMakeInstance->AddCacheEntry(
+ "CMAKE_GENERATOR_INSTANCE", vsInstance.c_str(),
+ "Generator instance identifier.", cmStateEnums::INTERNAL);
+ }
+
+ return true;
+}
+
+bool cmGlobalVisualStudio15Generator::GetVSInstance(std::string& dir) const
+{
+ return vsSetupAPIHelper.GetVSInstanceInfo(dir);
+}
+
bool cmGlobalVisualStudio15Generator::InitializeWindows(cmMakefile* mf)
{
// If the Win 8.1 SDK is installed then we can select a SDK matching
diff --git a/Source/cmGlobalVisualStudio15Generator.h b/Source/cmGlobalVisualStudio15Generator.h
index e93488243..4f4e0b97b 100644
--- a/Source/cmGlobalVisualStudio15Generator.h
+++ b/Source/cmGlobalVisualStudio15Generator.h
@@ -22,20 +22,25 @@ public:
const std::string& platformName);
static cmGlobalGeneratorFactory* NewFactory();
- virtual bool MatchesGeneratorName(const std::string& name) const;
+ bool MatchesGeneratorName(const std::string& name) const override;
- virtual void WriteSLNHeader(std::ostream& fout);
+ void WriteSLNHeader(std::ostream& fout) override;
+
+ const char* GetToolsVersion() override { return "15.0"; }
+
+ bool SetGeneratorInstance(std::string const& i, cmMakefile* mf) override;
+
+ bool GetVSInstance(std::string& dir) const;
- virtual const char* GetToolsVersion() { return "15.0"; }
protected:
bool InitializeWindows(cmMakefile* mf) override;
- virtual bool SelectWindowsStoreToolset(std::string& toolset) const;
+ bool SelectWindowsStoreToolset(std::string& toolset) const override;
- virtual const char* GetIDEVersion() { return "15.0"; }
+ const char* GetIDEVersion() override { return "15.0"; }
// Used to verify that the Desktop toolset for the current generator is
// installed on the machine.
- virtual bool IsWindowsDesktopToolsetInstalled() const;
+ bool IsWindowsDesktopToolsetInstalled() const override;
// These aren't virtual because we need to check if the selected version
// of the toolset is installed
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index 3b45c902c..45cc5834c 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -76,9 +76,8 @@ void cmGlobalVisualStudio71Generator::WriteSolutionConfigurations(
std::ostream& fout, std::vector<std::string> const& configs)
{
fout << "\tGlobalSection(SolutionConfiguration) = preSolution\n";
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
- fout << "\t\t" << *i << " = " << *i << "\n";
+ for (std::string const& i : configs) {
+ fout << "\t\t" << i << " = " << i << "\n";
}
fout << "\tEndGlobalSection\n";
}
@@ -143,9 +142,7 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
cmGeneratorTarget const* target)
{
VSDependSet const& depends = this->VSTargetDepends[target];
- for (VSDependSet::const_iterator di = depends.begin(); di != depends.end();
- ++di) {
- const char* name = di->c_str();
+ for (std::string const& name : depends) {
std::string guid = this->GetGUID(name);
if (guid.empty()) {
std::string m = "Target: ";
@@ -174,11 +171,10 @@ void cmGlobalVisualStudio71Generator::WriteExternalProject(
// project instead of in the global section
if (!depends.empty()) {
fout << "\tProjectSection(ProjectDependencies) = postProject\n";
- std::set<std::string>::const_iterator it;
- for (it = depends.begin(); it != depends.end(); ++it) {
- if (!it->empty()) {
- fout << "\t\t{" << this->GetGUID(it->c_str()) << "} = {"
- << this->GetGUID(it->c_str()) << "}\n";
+ for (std::string const& it : depends) {
+ if (!it.empty()) {
+ fout << "\t\t{" << this->GetGUID(it) << "} = {" << this->GetGUID(it)
+ << "}\n";
}
}
fout << "\tEndProjectSection\n";
@@ -198,31 +194,30 @@ void cmGlobalVisualStudio71Generator::WriteProjectConfigurations(
const std::string& platformName =
!platformMapping.empty() ? platformMapping : this->GetPlatformName();
std::string guid = this->GetGUID(name);
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
+ for (std::string const& i : configs) {
std::vector<std::string> mapConfig;
- const char* dstConfig = i->c_str();
+ const char* dstConfig = i.c_str();
if (target.GetProperty("EXTERNAL_MSPROJECT")) {
if (const char* m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
- cmSystemTools::UpperCase(*i))) {
+ cmSystemTools::UpperCase(i))) {
cmSystemTools::ExpandListArgument(m, mapConfig);
if (!mapConfig.empty()) {
dstConfig = mapConfig[0].c_str();
}
}
}
- fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << dstConfig
- << "|" << platformName << std::endl;
+ fout << "\t\t{" << guid << "}." << i << ".ActiveCfg = " << dstConfig << "|"
+ << platformName << std::endl;
std::set<std::string>::const_iterator ci =
- configsPartOfDefaultBuild.find(*i);
+ configsPartOfDefaultBuild.find(i);
if (!(ci == configsPartOfDefaultBuild.end())) {
- fout << "\t\t{" << guid << "}." << *i << ".Build.0 = " << dstConfig
- << "|" << platformName << std::endl;
+ fout << "\t\t{" << guid << "}." << i << ".Build.0 = " << dstConfig << "|"
+ << platformName << std::endl;
}
}
}
-// ouput standard header for dsw file
+// output standard header for dsw file
void cmGlobalVisualStudio71Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 8.00\n";
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 0ce02aa46..054c3421d 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -17,25 +17,24 @@ public:
const std::string& platformName = "");
protected:
- virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
- std::vector<cmLocalGenerator*>& generators);
+ void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root,
+ std::vector<cmLocalGenerator*>& generators) override;
virtual void WriteSolutionConfigurations(
std::ostream& fout, std::vector<std::string> const& configs);
- virtual void WriteProject(std::ostream& fout, const std::string& name,
- const char* path, const cmGeneratorTarget* t);
- virtual void WriteProjectDepends(std::ostream& fout, const std::string& name,
- const char* path,
- cmGeneratorTarget const* t);
- virtual void WriteProjectConfigurations(
+ void WriteProject(std::ostream& fout, const std::string& name,
+ const char* path, const cmGeneratorTarget* t) override;
+ void WriteProjectDepends(std::ostream& fout, const std::string& name,
+ const char* path,
+ cmGeneratorTarget const* t) override;
+ void WriteProjectConfigurations(
std::ostream& fout, const std::string& name,
cmGeneratorTarget const& target, std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const std::string& platformMapping = "");
- virtual void WriteExternalProject(std::ostream& fout,
- const std::string& name, const char* path,
- const char* typeGuid,
- const std::set<std::string>& depends);
- virtual void WriteSLNHeader(std::ostream& fout);
+ const std::string& platformMapping = "") override;
+ void WriteExternalProject(std::ostream& fout, const std::string& name,
+ const char* path, const char* typeGuid,
+ const std::set<std::string>& depends) override;
+ void WriteSLNHeader(std::ostream& fout) override;
// Folders are not supported by VS 7.1.
virtual bool UseFolderProperty() { return false; }
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index a14b5f753..c915dc5eb 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -334,9 +334,8 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile(
// output the SLN file
void cmGlobalVisualStudio7Generator::OutputSLNFile()
{
- std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- this->OutputSLNFile(it->second[0], it->second);
+ for (auto& it : this->ProjectMap) {
+ this->OutputSLNFile(it.second[0], it.second);
}
}
@@ -346,9 +345,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
{
// loop over again and write out configurations for each target
// in the solution
- for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
- tt != projectTargets.end(); ++tt) {
- cmGeneratorTarget const* target = *tt;
+ for (cmGeneratorTarget const* target : projectTargets) {
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -378,9 +375,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
VisualStudioFolders.clear();
std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
- for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
- tt != projectTargets.end(); ++tt) {
- cmGeneratorTarget const* target = *tt;
+ for (cmGeneratorTarget const* target : projectTargets) {
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -420,19 +415,18 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
std::string cumulativePath;
- for (std::vector<cmsys::String>::iterator iter = tokens.begin();
- iter != tokens.end(); ++iter) {
- if (!iter->size()) {
+ for (cmsys::String const& iter : tokens) {
+ if (!iter.size()) {
continue;
}
if (cumulativePath.empty()) {
- cumulativePath = "CMAKE_FOLDER_GUID_" + *iter;
+ cumulativePath = "CMAKE_FOLDER_GUID_" + iter;
} else {
VisualStudioFolders[cumulativePath].insert(cumulativePath + "/" +
- *iter);
+ iter);
- cumulativePath = cumulativePath + "/" + *iter;
+ cumulativePath = cumulativePath + "/" + iter;
}
}
@@ -447,9 +441,7 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
void cmGlobalVisualStudio7Generator::WriteTargetDepends(
std::ostream& fout, OrderedTargetDependSet const& projectTargets)
{
- for (OrderedTargetDependSet::const_iterator tt = projectTargets.begin();
- tt != projectTargets.end(); ++tt) {
- cmGeneratorTarget const* target = *tt;
+ for (cmGeneratorTarget const* target : projectTargets) {
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -467,11 +459,9 @@ void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
const char* prefix = "CMAKE_FOLDER_GUID_";
const std::string::size_type skip_prefix = strlen(prefix);
std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8";
- for (std::map<std::string, std::set<std::string>>::iterator iter =
- VisualStudioFolders.begin();
- iter != VisualStudioFolders.end(); ++iter) {
- std::string fullName = iter->first;
- std::string guid = this->GetGUID(fullName.c_str());
+ for (auto const& iter : VisualStudioFolders) {
+ std::string fullName = iter.first;
+ std::string guid = this->GetGUID(fullName);
std::replace(fullName.begin(), fullName.end(), '/', '\\');
if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix)) {
@@ -487,16 +477,13 @@ void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout)
void cmGlobalVisualStudio7Generator::WriteFoldersContent(std::ostream& fout)
{
- for (std::map<std::string, std::set<std::string>>::iterator iter =
- VisualStudioFolders.begin();
- iter != VisualStudioFolders.end(); ++iter) {
- std::string key(iter->first);
- std::string guidParent(this->GetGUID(key.c_str()));
+ for (auto const& iter : VisualStudioFolders) {
+ std::string key(iter.first);
+ std::string guidParent(this->GetGUID(key));
- for (std::set<std::string>::iterator it = iter->second.begin();
- it != iter->second.end(); ++it) {
- std::string value(*it);
- std::string guid(this->GetGUID(value.c_str()));
+ for (std::string const& it : iter.second) {
+ std::string value(it);
+ std::string guid(this->GetGUID(value));
fout << "\t\t{" << guid << "} = {" << guidParent << "}\n";
}
@@ -525,11 +512,10 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
bool extensibilityAddInsOverridden = false;
const std::vector<std::string> propKeys =
root->GetMakefile()->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator it = propKeys.begin();
- it != propKeys.end(); ++it) {
- if (it->find("VS_GLOBAL_SECTION_") == 0) {
+ for (std::string const& it : propKeys) {
+ if (it.find("VS_GLOBAL_SECTION_") == 0) {
std::string sectionType;
- std::string name = it->substr(18);
+ std::string name = it.substr(18);
if (name.find("PRE_") == 0) {
name = name.substr(4);
sectionType = "preSolution";
@@ -549,17 +535,15 @@ void cmGlobalVisualStudio7Generator::WriteSLNGlobalSections(
}
fout << "\tGlobalSection(" << name << ") = " << sectionType << "\n";
std::vector<std::string> keyValuePairs;
- cmSystemTools::ExpandListArgument(
- root->GetMakefile()->GetProperty(it->c_str()), keyValuePairs);
- for (std::vector<std::string>::const_iterator itPair =
- keyValuePairs.begin();
- itPair != keyValuePairs.end(); ++itPair) {
- const std::string::size_type posEqual = itPair->find('=');
+ cmSystemTools::ExpandListArgument(root->GetMakefile()->GetProperty(it),
+ keyValuePairs);
+ for (std::string const& itPair : keyValuePairs) {
+ const std::string::size_type posEqual = itPair.find('=');
if (posEqual != std::string::npos) {
const std::string key =
- cmSystemTools::TrimWhitespace(itPair->substr(0, posEqual));
+ cmSystemTools::TrimWhitespace(itPair.substr(0, posEqual));
const std::string value =
- cmSystemTools::TrimWhitespace(itPair->substr(posEqual + 1));
+ cmSystemTools::TrimWhitespace(itPair.substr(posEqual + 1));
fout << "\t\t" << key << " = " << value << "\n";
if (key == "SolutionGuid") {
addGuid = false;
@@ -618,14 +602,13 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
"\t<Configurations>\n"
;
/* clang-format on */
- for (std::vector<std::string>::iterator i = configs.begin();
- i != configs.end(); ++i) {
+ for (std::string const& i : configs) {
/* clang-format off */
fout <<
"\t\t<Configuration\n"
- "\t\t\tName=\"" << *i << "|Win32\"\n"
- "\t\t\tOutputDirectory=\"" << *i << "\"\n"
- "\t\t\tIntermediateDirectory=\"" << pname << ".dir\\" << *i << "\"\n"
+ "\t\t\tName=\"" << i << "|Win32\"\n"
+ "\t\t\tOutputDirectory=\"" << i << "\"\n"
+ "\t\t\tIntermediateDirectory=\"" << pname << ".dir\\" << i << "\"\n"
"\t\t\tConfigurationType=\"10\"\n"
"\t\t\tUseOfMFC=\"0\"\n"
"\t\t\tATLMinimizesCRunTimeLibraryUsage=\"FALSE\"\n"
@@ -696,23 +679,21 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
std::vector<std::string> targetNames;
targetNames.push_back("INSTALL");
targetNames.push_back("PACKAGE");
- for (std::vector<std::string>::const_iterator t = targetNames.begin();
- t != targetNames.end(); ++t) {
- // check if target <*t> is part of default build
- if (target->GetName() == *t) {
+ for (std::string const& t : targetNames) {
+ // check if target <t> is part of default build
+ if (target->GetName() == t) {
const std::string propertyName =
- "CMAKE_VS_INCLUDE_" + *t + "_TO_DEFAULT_BUILD";
- // inspect CMAKE_VS_INCLUDE_<*t>_TO_DEFAULT_BUILD properties
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
+ "CMAKE_VS_INCLUDE_" + t + "_TO_DEFAULT_BUILD";
+ // inspect CMAKE_VS_INCLUDE_<t>_TO_DEFAULT_BUILD properties
+ for (std::string const& i : configs) {
const char* propertyValue =
target->Target->GetMakefile()->GetDefinition(propertyName);
cmGeneratorExpression ge;
std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(propertyValue);
if (cmSystemTools::IsOn(
- cge->Evaluate(target->GetLocalGenerator(), *i))) {
- activeConfigs.insert(*i);
+ cge->Evaluate(target->GetLocalGenerator(), i))) {
+ activeConfigs.insert(i);
}
}
}
@@ -724,12 +705,11 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
return activeConfigs;
}
// inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
+ for (std::string const& i : configs) {
const char* propertyValue =
- target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str());
+ target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i);
if (cmSystemTools::IsOff(propertyValue)) {
- activeConfigs.insert(*i);
+ activeConfigs.insert(i);
}
}
return activeConfigs;
@@ -738,9 +718,8 @@ std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild(
bool cmGlobalVisualStudio7Generator::IsDependedOn(
OrderedTargetDependSet const& projectTargets, cmGeneratorTarget const* gtIn)
{
- for (OrderedTargetDependSet::const_iterator l = projectTargets.begin();
- l != projectTargets.end(); ++l) {
- TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(*l);
+ for (cmTargetDepend const& l : projectTargets) {
+ TargetDependSet const& tgtdeps = this->GetTargetDirectDepends(l);
if (tgtdeps.count(gtIn)) {
return true;
}
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index c5aced44f..8d1bdc0cc 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -26,11 +26,11 @@ public:
std::string const& GetPlatformName() const;
///! Create a local generator appropriate to this Global Generator
- virtual cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf);
+ cmLocalGenerator* CreateLocalGenerator(cmMakefile* mf) override;
- virtual bool SetSystemName(std::string const& s, cmMakefile* mf);
+ bool SetSystemName(std::string const& s, cmMakefile* mf) override;
- virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
+ bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
/**
* Utilized by the generator factory to determine if this generator
@@ -48,19 +48,21 @@ public:
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
/**
* Try running cmake and building a file. This is used for dynamically
* loaded commands, not as part of the usual build process.
*/
- virtual void GenerateBuildCommand(
- std::vector<std::string>& makeCommand, const std::string& makeProgram,
- const std::string& projectName, const std::string& projectDir,
- const std::string& targetName, const std::string& config, bool fast,
- bool verbose,
- std::vector<std::string> const& makeOptions = std::vector<std::string>());
+ void GenerateBuildCommand(std::vector<std::string>& makeCommand,
+ const std::string& makeProgram,
+ const std::string& projectName,
+ const std::string& projectDir,
+ const std::string& targetName,
+ const std::string& config, bool fast, bool verbose,
+ std::vector<std::string> const& makeOptions =
+ std::vector<std::string>()) override;
/**
* Generate the DSW workspace file.
@@ -71,13 +73,13 @@ public:
std::string GetGUID(std::string const& name);
/** Append the subdirectory for the given configuration. */
- virtual void AppendDirectoryForConfig(const std::string& prefix,
- const std::string& config,
- const std::string& suffix,
- std::string& dir);
+ void AppendDirectoryForConfig(const std::string& prefix,
+ const std::string& config,
+ const std::string& suffix,
+ std::string& dir) override;
///! What is the configurations directory variable called?
- virtual const char* GetCMakeCFGIntDir() const
+ const char* GetCMakeCFGIntDir() const override
{
return "$(ConfigurationName)";
}
@@ -103,7 +105,7 @@ public:
cmIDEFlagTable const* ExtraFlagTable;
protected:
- virtual void Generate();
+ void Generate() override;
virtual const char* GetIDEVersion() = 0;
std::string const& GetDevEnvCommand();
@@ -129,7 +131,7 @@ protected:
cmLocalGenerator* root);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout) = 0;
- virtual std::string WriteUtilityDepend(const cmGeneratorTarget* target);
+ std::string WriteUtilityDepend(const cmGeneratorTarget* target) override;
virtual void WriteTargetsToSolution(
std::ostream& fout, cmLocalGenerator* root,
@@ -170,7 +172,7 @@ private:
char* IntelProjectVersion;
std::string DevEnvCommand;
bool DevEnvCommandInitialized;
- virtual std::string GetVSMakeProgram() { return this->GetDevEnvCommand(); }
+ std::string GetVSMakeProgram() override { return this->GetDevEnvCommand(); }
};
#define CMAKE_CHECK_BUILD_SYSTEM_TARGET "ZERO_CHECK"
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index cc1d1a27b..ab8ad7022 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -66,10 +66,8 @@ public:
parser.ParseVersion("8.0");
const std::vector<std::string>& availablePlatforms =
parser.GetAvailablePlatforms();
- for (std::vector<std::string>::const_iterator i =
- availablePlatforms.begin();
- i != availablePlatforms.end(); ++i) {
- names.push_back("Visual Studio 8 2005 " + *i);
+ for (std::string const& i : availablePlatforms) {
+ names.push_back("Visual Studio 8 2005 " + i);
}
}
@@ -117,9 +115,8 @@ std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand()
void cmGlobalVisualStudio8Generator::EnableLanguage(
std::vector<std::string> const& lang, cmMakefile* mf, bool optional)
{
- for (std::vector<std::string>::const_iterator it = lang.begin();
- it != lang.end(); ++it) {
- if (*it == "ASM_MASM") {
+ for (std::string const& it : lang) {
+ if (it == "ASM_MASM") {
this->MasmEnabled = true;
}
}
@@ -146,7 +143,7 @@ bool cmGlobalVisualStudio8Generator::SetGeneratorPlatform(std::string const& p,
}
}
-// ouput standard header for dsw file
+// output standard header for dsw file
void cmGlobalVisualStudio8Generator::WriteSLNHeader(std::ostream& fout)
{
fout << "Microsoft Visual Studio Solution File, Format Version 9.00\n";
@@ -225,9 +222,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
}
cmCustomCommandLines noCommandLines;
- cmTarget* tgt =
- mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false,
- no_working_directory, no_depends, noCommandLines);
+ cmTarget* tgt = mf->AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
+ false, no_working_directory, no_depends, noCommandLines);
cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg);
lg->AddGeneratorTarget(gt);
@@ -249,10 +246,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
stampListFile += stampList;
std::string stampFile;
cmGeneratedFileStream fout(stampListFile.c_str());
- for (std::vector<cmLocalGenerator*>::const_iterator gi =
- generators.begin();
- gi != generators.end(); ++gi) {
- stampFile = (*gi)->GetMakefile()->GetCurrentBinaryDirectory();
+ for (cmLocalGenerator const* gi : generators) {
+ stampFile = gi->GetMakefile()->GetCurrentBinaryDirectory();
stampFile += "/";
stampFile += cmake::GetCMakeFilesDirectoryPostSlash();
stampFile += "generate.stamp";
@@ -323,10 +318,9 @@ void cmGlobalVisualStudio8Generator::AddExtraIDETargets()
const std::vector<cmGeneratorTarget*>& tgts =
this->LocalGenerators[i]->GetGeneratorTargets();
// All targets depend on the build-system check target.
- for (std::vector<cmGeneratorTarget*>::const_iterator ti = tgts.begin();
- ti != tgts.end(); ++ti) {
- if ((*ti)->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
- (*ti)->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
+ for (cmGeneratorTarget const* ti : tgts) {
+ if (ti->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ ti->Target->AddUtility(CMAKE_CHECK_BUILD_SYSTEM_TARGET);
}
}
}
@@ -337,10 +331,9 @@ void cmGlobalVisualStudio8Generator::WriteSolutionConfigurations(
std::ostream& fout, std::vector<std::string> const& configs)
{
fout << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n";
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
- fout << "\t\t" << *i << "|" << this->GetPlatformName() << " = " << *i
- << "|" << this->GetPlatformName() << "\n";
+ for (std::string const& i : configs) {
+ fout << "\t\t" << i << "|" << this->GetPlatformName() << " = " << i << "|"
+ << this->GetPlatformName() << "\n";
}
fout << "\tEndGlobalSection\n";
}
@@ -352,35 +345,34 @@ void cmGlobalVisualStudio8Generator::WriteProjectConfigurations(
std::string const& platformMapping)
{
std::string guid = this->GetGUID(name);
- for (std::vector<std::string>::const_iterator i = configs.begin();
- i != configs.end(); ++i) {
+ for (std::string const& i : configs) {
std::vector<std::string> mapConfig;
- const char* dstConfig = i->c_str();
+ const char* dstConfig = i.c_str();
if (target.GetProperty("EXTERNAL_MSPROJECT")) {
if (const char* m = target.GetProperty("MAP_IMPORTED_CONFIG_" +
- cmSystemTools::UpperCase(*i))) {
+ cmSystemTools::UpperCase(i))) {
cmSystemTools::ExpandListArgument(m, mapConfig);
if (!mapConfig.empty()) {
dstConfig = mapConfig[0].c_str();
}
}
}
- fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
+ fout << "\t\t{" << guid << "}." << i << "|" << this->GetPlatformName()
<< ".ActiveCfg = " << dstConfig << "|"
<< (!platformMapping.empty() ? platformMapping
: this->GetPlatformName())
<< "\n";
std::set<std::string>::const_iterator ci =
- configsPartOfDefaultBuild.find(*i);
+ configsPartOfDefaultBuild.find(i);
if (!(ci == configsPartOfDefaultBuild.end())) {
- fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
+ fout << "\t\t{" << guid << "}." << i << "|" << this->GetPlatformName()
<< ".Build.0 = " << dstConfig << "|"
<< (!platformMapping.empty() ? platformMapping
: this->GetPlatformName())
<< "\n";
}
if (this->NeedsDeploy(target.GetType())) {
- fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName()
+ fout << "\t\t{" << guid << "}." << i << "|" << this->GetPlatformName()
<< ".Deploy.0 = " << dstConfig << "|"
<< (!platformMapping.empty() ? platformMapping
: this->GetPlatformName())
@@ -410,12 +402,11 @@ void cmGlobalVisualStudio8Generator::WriteProjectDepends(
{
TargetDependSet const& unordered = this->GetTargetDirectDepends(gt);
OrderedTargetDependSet depends(unordered, std::string());
- for (OrderedTargetDependSet::const_iterator i = depends.begin();
- i != depends.end(); ++i) {
- if ((*i)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmTargetDepend const& i : depends) {
+ if (i->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- std::string guid = this->GetGUID((*i)->GetName().c_str());
+ std::string guid = this->GetGUID(i->GetName());
fout << "\t\t{" << guid << "} = {" << guid << "}\n";
}
}
@@ -424,11 +415,9 @@ bool cmGlobalVisualStudio8Generator::NeedLinkLibraryDependencies(
cmGeneratorTarget* target)
{
// Look for utility dependencies that magically link.
- for (std::set<std::string>::const_iterator ui =
- target->GetUtilities().begin();
- ui != target->GetUtilities().end(); ++ui) {
+ for (std::string const& ui : target->GetUtilities()) {
if (cmGeneratorTarget* depTarget =
- target->GetLocalGenerator()->FindGeneratorTargetToUse(ui->c_str())) {
+ target->GetLocalGenerator()->FindGeneratorTargetToUse(ui)) {
if (depTarget->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
depTarget->GetProperty("EXTERNAL_MSPROJECT")) {
// This utility dependency names an external .vcproj target.
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index 4723b83ba..af83e4f1b 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -18,42 +18,42 @@ public:
static cmGlobalGeneratorFactory* NewFactory();
///! Get the name for the generator.
- virtual std::string GetName() const { return this->Name; }
+ std::string GetName() const override { return this->Name; }
/** Get the name of the main stamp list file. */
static std::string GetGenerateStampList();
- virtual void EnableLanguage(std::vector<std::string> const& languages,
- cmMakefile*, bool optional);
+ void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
+ bool optional) override;
virtual void AddPlatformDefinitions(cmMakefile* mf);
- virtual bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf);
+ bool SetGeneratorPlatform(std::string const& p, cmMakefile* mf) override;
/**
* Override Configure and Generate to add the build-system check
* target.
*/
- virtual void Configure();
+ void Configure() override;
/**
* Where does this version of Visual Studio look for macros for the
* current user? Returns the empty string if this version of Visual
* Studio does not implement support for VB macros.
*/
- virtual std::string GetUserMacrosDirectory();
+ std::string GetUserMacrosDirectory() override;
/**
* What is the reg key path to "vsmacros" for this version of Visual
* Studio?
*/
- virtual std::string GetUserMacrosRegKeyBase();
+ std::string GetUserMacrosRegKeyBase() override;
/** Return true if the target project file should have the option
LinkLibraryDependencies and link to .sln dependencies. */
- virtual bool NeedLinkLibraryDependencies(cmGeneratorTarget* target);
+ bool NeedLinkLibraryDependencies(cmGeneratorTarget* target) override;
/** Return true if building for Windows CE */
- virtual bool TargetsWindowsCE() const
+ bool TargetsWindowsCE() const override
{
return !this->WindowsCEVersion.empty();
}
@@ -62,12 +62,12 @@ public:
bool IsExpressEdition() const { return this->ExpressEdition; }
protected:
- virtual void AddExtraIDETargets();
- virtual const char* GetIDEVersion() { return "8.0"; }
+ void AddExtraIDETargets() override;
+ const char* GetIDEVersion() override { return "8.0"; }
- virtual std::string FindDevEnvCommand();
+ std::string FindDevEnvCommand() override;
- virtual bool VSLinksDependencies() const { return false; }
+ bool VSLinksDependencies() const override { return false; }
bool AddCheckTarget();
@@ -75,18 +75,18 @@ protected:
virtual bool NeedsDeploy(cmStateEnums::TargetType type) const;
static cmIDEFlagTable const* GetExtraFlagTableVS8();
- virtual void WriteSLNHeader(std::ostream& fout);
- virtual void WriteSolutionConfigurations(
- std::ostream& fout, std::vector<std::string> const& configs);
- virtual void WriteProjectConfigurations(
+ void WriteSLNHeader(std::ostream& fout) override;
+ void WriteSolutionConfigurations(
+ std::ostream& fout, std::vector<std::string> const& configs) override;
+ void WriteProjectConfigurations(
std::ostream& fout, const std::string& name,
cmGeneratorTarget const& target, std::vector<std::string> const& configs,
const std::set<std::string>& configsPartOfDefaultBuild,
- const std::string& platformMapping = "");
- virtual bool ComputeTargetDepends();
- virtual void WriteProjectDepends(std::ostream& fout, const std::string& name,
- const char* path,
- const cmGeneratorTarget* t);
+ const std::string& platformMapping = "") override;
+ bool ComputeTargetDepends() override;
+ void WriteProjectDepends(std::ostream& fout, const std::string& name,
+ const char* path,
+ const cmGeneratorTarget* t) override;
bool UseFolderProperty();
diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx
index 0abb3488e..7ac3a6f09 100644
--- a/Source/cmGlobalVisualStudio9Generator.cxx
+++ b/Source/cmGlobalVisualStudio9Generator.cxx
@@ -68,10 +68,8 @@ public:
parser.ParseVersion("9.0");
const std::vector<std::string>& availablePlatforms =
parser.GetAvailablePlatforms();
- for (std::vector<std::string>::const_iterator i =
- availablePlatforms.begin();
- i != availablePlatforms.end(); ++i) {
- names.push_back("Visual Studio 9 2008 " + *i);
+ for (std::string const& i : availablePlatforms) {
+ names.push_back("Visual Studio 9 2008 " + i);
}
}
diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h
index fbc1f5d07..37efb9ccd 100644
--- a/Source/cmGlobalVisualStudio9Generator.h
+++ b/Source/cmGlobalVisualStudio9Generator.h
@@ -21,23 +21,23 @@ public:
* Try to determine system information such as shared library
* extension, pthreads, byte order etc.
*/
- virtual void WriteSLNHeader(std::ostream& fout);
+ void WriteSLNHeader(std::ostream& fout) override;
/**
* Where does this version of Visual Studio look for macros for the
* current user? Returns the empty string if this version of Visual
* Studio does not implement support for VB macros.
*/
- virtual std::string GetUserMacrosDirectory();
+ std::string GetUserMacrosDirectory() override;
/**
* What is the reg key path to "vsmacros" for this version of Visual
* Studio?
*/
- virtual std::string GetUserMacrosRegKeyBase();
+ std::string GetUserMacrosRegKeyBase() override;
protected:
- virtual const char* GetIDEVersion() { return "9.0"; }
+ const char* GetIDEVersion() override { return "9.0"; }
private:
class Factory;
friend class Factory;
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 0651536a9..a4570e160 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -4,7 +4,10 @@
#include "cmGlobalVisualStudioGenerator.h"
#include "cmsys/Encoding.hxx"
+#include <future>
#include <iostream>
+#include <objbase.h>
+#include <shellapi.h>
#include <windows.h>
#include "cmAlgorithms.h"
@@ -58,16 +61,15 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
const char* no_working_dir = 0;
std::vector<std::string> no_depends;
cmCustomCommandLines no_commands;
- std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- std::vector<cmLocalGenerator*>& gen = it->second;
+ for (auto const& it : this->ProjectMap) {
+ std::vector<cmLocalGenerator*> const& gen = it.second;
// add the ALL_BUILD to the first local generator of each project
if (!gen.empty()) {
// Use no actual command lines so that the target itself is not
// considered always out of date.
cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand(
- "ALL_BUILD", true, no_working_dir, no_depends, no_commands, false,
- "Build all projects");
+ "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, no_working_dir,
+ no_depends, no_commands, false, "Build all projects");
cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]);
gen[0]->AddGeneratorTarget(gt);
@@ -80,14 +82,10 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
}
// Now make all targets depend on the ALL_BUILD target
- for (std::vector<cmLocalGenerator*>::iterator i = gen.begin();
- i != gen.end(); ++i) {
- const std::vector<cmGeneratorTarget*>& targets =
- (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator t =
- targets.begin();
- t != targets.end(); ++t) {
- cmGeneratorTarget* tgt = *t;
+ for (cmLocalGenerator const* i : gen) {
+ std::vector<cmGeneratorTarget*> const& targets =
+ i->GetGeneratorTargets();
+ for (cmGeneratorTarget* tgt : targets) {
if (tgt->GetType() == cmStateEnums::GLOBAL_TARGET ||
tgt->IsImported()) {
continue;
@@ -103,15 +101,6 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
// Configure CMake Visual Studio macros, for this user on this version
// of Visual Studio.
this->ConfigureCMakeVisualStudioMacros();
-
- // Add CMakeLists.txt with custom command to rerun CMake.
- for (std::vector<cmLocalGenerator*>::const_iterator lgi =
- this->LocalGenerators.begin();
- lgi != this->LocalGenerators.end(); ++lgi) {
- cmLocalVisualStudioGenerator* lg =
- static_cast<cmLocalVisualStudioGenerator*>(*lgi);
- lg->AddCMakeListsRules();
- }
}
void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory(
@@ -249,10 +238,9 @@ void cmGlobalVisualStudioGenerator::FillLinkClosure(
{
if (linked.insert(target).second) {
TargetDependSet const& depends = this->GetTargetDirectDepends(target);
- for (TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- if (di->IsLink()) {
- this->FillLinkClosure(*di, linked);
+ for (cmTargetDepend const& di : depends) {
+ if (di.IsLink()) {
+ this->FillLinkClosure(di, linked);
}
}
}
@@ -281,10 +269,9 @@ void cmGlobalVisualStudioGenerator::FollowLinkDepends(
// Static library targets do not list their link dependencies so
// we must follow them transitively now.
TargetDependSet const& depends = this->GetTargetDirectDepends(target);
- for (TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- if (di->IsLink()) {
- this->FollowLinkDepends(*di, linked);
+ for (cmTargetDepend const& di : depends) {
+ if (di.IsLink()) {
+ this->FollowLinkDepends(di, linked);
}
}
}
@@ -295,17 +282,13 @@ bool cmGlobalVisualStudioGenerator::ComputeTargetDepends()
if (!this->cmGlobalGenerator::ComputeTargetDepends()) {
return false;
}
- std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- std::vector<cmLocalGenerator*>& gen = it->second;
- for (std::vector<cmLocalGenerator*>::iterator i = gen.begin();
- i != gen.end(); ++i) {
- const std::vector<cmGeneratorTarget*>& targets =
- (*i)->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator ti =
- targets.begin();
- ti != targets.end(); ++ti) {
- this->ComputeVSTargetDepends(*ti);
+ for (auto const& it : this->ProjectMap) {
+ std::vector<cmLocalGenerator*> const& gen = it.second;
+ for (const cmLocalGenerator* i : gen) {
+ std::vector<cmGeneratorTarget*> const& targets =
+ i->GetGeneratorTargets();
+ for (cmGeneratorTarget* ti : targets) {
+ this->ComputeVSTargetDepends(ti);
}
}
}
@@ -355,22 +338,20 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(
// due to behavior (2), but they do not really need to.
std::set<cmGeneratorTarget const*> linkDepends;
if (target->GetType() != cmStateEnums::STATIC_LIBRARY) {
- for (TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- cmTargetDepend dep = *di;
+ for (cmTargetDepend const& di : depends) {
+ cmTargetDepend dep = di;
if (dep.IsLink()) {
- this->FollowLinkDepends(*di, linkDepends);
+ this->FollowLinkDepends(di, linkDepends);
}
}
}
// Collect explicit util dependencies (add_dependencies).
std::set<cmGeneratorTarget const*> utilDepends;
- for (TargetDependSet::const_iterator di = depends.begin();
- di != depends.end(); ++di) {
- cmTargetDepend dep = *di;
+ for (cmTargetDepend const& di : depends) {
+ cmTargetDepend dep = di;
if (dep.IsUtil()) {
- this->FollowLinkDepends(*di, utilDepends);
+ this->FollowLinkDepends(di, utilDepends);
}
}
@@ -382,16 +363,12 @@ void cmGlobalVisualStudioGenerator::ComputeVSTargetDepends(
}
// Emit link dependencies.
- for (std::set<cmGeneratorTarget const*>::iterator di = linkDepends.begin();
- di != linkDepends.end(); ++di) {
- cmGeneratorTarget const* dep = *di;
+ for (cmGeneratorTarget const* dep : linkDepends) {
vsTargetDepend.insert(dep->GetName());
}
// Emit util dependencies. Possibly use intermediate targets.
- for (std::set<cmGeneratorTarget const*>::iterator di = utilDepends.begin();
- di != utilDepends.end(); ++di) {
- cmGeneratorTarget const* dgt = *di;
+ for (cmGeneratorTarget const* dgt : utilDepends) {
if (allowLinkable || !VSLinkable(dgt) || linked.count(dgt)) {
// Direct dependency allowed.
vsTargetDepend.insert(dgt->GetName());
@@ -821,9 +798,8 @@ cmGlobalVisualStudioGenerator::OrderedTargetDependSet::OrderedTargetDependSet(
TargetSet const& targets, std::string const& first)
: derived(TargetCompare(first))
{
- for (TargetSet::const_iterator it = targets.begin(); it != targets.end();
- ++it) {
- this->insert(*it);
+ for (cmGeneratorTarget const* it : targets) {
+ this->insert(it);
}
}
@@ -857,10 +833,8 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
std::vector<cmSourceFile const*> objectSources;
gt->GetObjectSources(objectSources, configName);
std::map<cmSourceFile const*, std::string> mapping;
- for (std::vector<cmSourceFile const*>::const_iterator it =
- objectSources.begin();
- it != objectSources.end(); ++it) {
- mapping[*it];
+ for (cmSourceFile const* it : objectSources) {
+ mapping[it];
}
gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
std::string obj_dir = gt->ObjectDirectory;
@@ -885,12 +859,10 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
if (mdi->WindowsExportAllSymbols) {
std::vector<std::string> objs;
- for (std::vector<cmSourceFile const*>::const_iterator it =
- objectSources.begin();
- it != objectSources.end(); ++it) {
+ for (cmSourceFile const* it : objectSources) {
// Find the object file name corresponding to this source file.
std::map<cmSourceFile const*, std::string>::const_iterator map_it =
- mapping.find(*it);
+ mapping.find(it);
// It must exist because we populated the mapping just above.
assert(!map_it->second.empty());
std::string objFile = obj_dir + map_it->second;
@@ -898,15 +870,12 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
}
std::vector<cmSourceFile const*> externalObjectSources;
gt->GetExternalObjects(externalObjectSources, configName);
- for (std::vector<cmSourceFile const*>::const_iterator it =
- externalObjectSources.begin();
- it != externalObjectSources.end(); ++it) {
- objs.push_back((*it)->GetFullPath());
+ for (cmSourceFile const* it : externalObjectSources) {
+ objs.push_back(it->GetFullPath());
}
- for (std::vector<std::string>::iterator it = objs.begin();
- it != objs.end(); ++it) {
- std::string objFile = *it;
+ for (std::string const& it : objs) {
+ std::string objFile = it;
// replace $(ConfigurationName) in the object names
cmSystemTools::ReplaceString(objFile, this->GetCMakeCFGIntDir(),
configName.c_str());
@@ -916,10 +885,8 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
}
}
- for (std::vector<cmSourceFile const*>::const_iterator i =
- mdi->Sources.begin();
- i != mdi->Sources.end(); ++i) {
- fout << (*i)->GetFullPath() << "\n";
+ for (cmSourceFile const* i : mdi->Sources) {
+ fout << i->GetFullPath() << "\n";
}
cmCustomCommandLines commandLines;
@@ -928,3 +895,33 @@ void cmGlobalVisualStudioGenerator::AddSymbolExportCommand(
commandLines, "Auto build dll exports", ".");
commands.push_back(command);
}
+
+static bool OpenSolution(std::string sln)
+{
+ HRESULT comInitialized =
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
+ if (FAILED(comInitialized)) {
+ return false;
+ }
+
+ HINSTANCE hi =
+ ShellExecuteA(NULL, "open", sln.c_str(), NULL, NULL, SW_SHOWNORMAL);
+
+ CoUninitialize();
+
+ return reinterpret_cast<intptr_t>(hi) > 32;
+}
+
+bool cmGlobalVisualStudioGenerator::Open(const std::string& bindir,
+ const std::string& projectName,
+ bool dryRun)
+{
+ std::string buildDir = cmSystemTools::ConvertToOutputPath(bindir);
+ std::string sln = buildDir + "\\" + projectName + ".sln";
+
+ if (dryRun) {
+ return cmSystemTools::FileExists(sln, true);
+ }
+
+ return std::async(std::launch::async, OpenSolution, sln).get();
+}
diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h
index 62bfd3bdb..75b7f2200 100644
--- a/Source/cmGlobalVisualStudioGenerator.h
+++ b/Source/cmGlobalVisualStudioGenerator.h
@@ -96,11 +96,13 @@ public:
/** Return true if the generated build tree may contain multiple builds.
i.e. "Can I build Debug and Release in the same tree?" */
- virtual bool IsMultiConfig() const { return true; }
+ bool IsMultiConfig() const override { return true; }
/** Return true if building for Windows CE */
virtual bool TargetsWindowsCE() const { return false; }
+ bool IsIncludeExternalMSProjectSupported() const override { return true; }
+
class TargetSet : public std::set<cmGeneratorTarget const*>
{
};
@@ -120,8 +122,8 @@ public:
bool FindMakeProgram(cmMakefile*) override;
- virtual std::string ExpandCFGIntDir(const std::string& str,
- const std::string& config) const;
+ std::string ExpandCFGIntDir(const std::string& str,
+ const std::string& config) const override;
void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const;
@@ -131,8 +133,11 @@ public:
std::vector<cmCustomCommand>& commands,
std::string const& configName);
+ bool Open(const std::string& bindir, const std::string& projectName,
+ bool dryRun) override;
+
protected:
- virtual void AddExtraIDETargets();
+ void AddExtraIDETargets() override;
// Does this VS version link targets to each other if there are
// dependencies in the SLN file? This was done for VS versions
@@ -141,7 +146,7 @@ protected:
virtual const char* GetIDEVersion() = 0;
- virtual bool ComputeTargetDepends();
+ bool ComputeTargetDepends() override;
class VSDependSet : public std::set<std::string>
{
};
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index c79ee475c..8f6107178 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -35,6 +35,11 @@
struct cmLinkImplementation;
+#if defined(CMAKE_BUILD_WITH_CMAKE) && defined(__APPLE__)
+#define HAVE_APPLICATION_SERVICES
+#include <ApplicationServices/ApplicationServices.h>
+#endif
+
#if defined(CMAKE_BUILD_WITH_CMAKE)
#include "cmXMLParser.h"
@@ -171,7 +176,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory::CreateGlobalGenerator(
std::string versionFile;
{
std::string out;
- std::string::size_type pos;
+ std::string::size_type pos = 0;
if (cmSystemTools::RunSingleCommand("xcode-select --print-path", &out,
nullptr, nullptr, nullptr,
cmSystemTools::OUTPUT_NONE) &&
@@ -287,6 +292,35 @@ void cmGlobalXCodeGenerator::EnableLanguage(
this->ComputeArchitectures(mf);
}
+bool cmGlobalXCodeGenerator::Open(const std::string& bindir,
+ const std::string& projectName, bool dryRun)
+{
+ bool ret = false;
+
+#ifdef HAVE_APPLICATION_SERVICES
+ std::string url = bindir + "/" + projectName + ".xcodeproj";
+
+ if (dryRun) {
+ return cmSystemTools::FileExists(url, false);
+ }
+
+ CFStringRef cfStr = CFStringCreateWithCString(
+ kCFAllocatorDefault, url.c_str(), kCFStringEncodingUTF8);
+ if (cfStr) {
+ CFURLRef cfUrl = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, cfStr,
+ kCFURLPOSIXPathStyle, true);
+ if (cfUrl) {
+ OSStatus err = LSOpenCFURLRef(cfUrl, nullptr);
+ ret = err == noErr;
+ CFRelease(cfUrl);
+ }
+ CFRelease(cfStr);
+ }
+#endif
+
+ return ret;
+}
+
void cmGlobalXCodeGenerator::GenerateBuildCommand(
std::vector<std::string>& makeCommand, const std::string& makeProgram,
const std::string& projectName, const std::string& /*projectDir*/,
@@ -334,14 +368,13 @@ cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf)
void cmGlobalXCodeGenerator::AddExtraIDETargets()
{
- std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
// make sure extra targets are added before calling
// the parent generate which will call trace depends
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- cmLocalGenerator* root = it->second[0];
+ for (auto keyVal : this->ProjectMap) {
+ cmLocalGenerator* root = keyVal.second[0];
this->SetGenerationRoot(root);
// add ALL_BUILD, INSTALL, etc
- this->AddExtraTargets(root, it->second);
+ this->AddExtraTargets(root, keyVal.second);
}
}
@@ -351,12 +384,22 @@ void cmGlobalXCodeGenerator::Generate()
if (cmSystemTools::GetErrorOccuredFlag()) {
return;
}
- std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it;
- for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) {
- cmLocalGenerator* root = it->second[0];
+ for (auto keyVal : this->ProjectMap) {
+ cmLocalGenerator* root = keyVal.second[0];
+
+ bool generateTopLevelProjectOnly =
+ root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+
+ if (generateTopLevelProjectOnly) {
+ cmStateSnapshot snp = root->GetStateSnapshot();
+ if (snp.GetBuildsystemDirectoryParent().IsValid()) {
+ continue;
+ }
+ }
+
this->SetGenerationRoot(root);
// now create the project
- this->OutputXCodeProject(root, it->second);
+ this->OutputXCodeProject(root, keyVal.second);
}
}
@@ -397,19 +440,13 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// Add ALL_BUILD
const char* no_working_directory = nullptr;
std::vector<std::string> no_depends;
- cmTarget* allbuild =
- mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory,
- "echo", "Build all projects");
+ cmTarget* allbuild = mf->AddUtilityCommand(
+ "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, no_depends,
+ no_working_directory, "echo", "Build all projects");
cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root);
root->AddGeneratorTarget(allBuildGt);
- // Refer to the main build configuration file for easy editing.
- std::string listfile = root->GetCurrentSourceDirectory();
- listfile += "/";
- listfile += "CMakeLists.txt";
- allBuildGt->AddSource(listfile);
-
// Add XCODE depend helper
std::string dir = root->GetCurrentBinaryDirectory();
cmCustomCommandLine makeHelper;
@@ -422,14 +459,18 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
// Add ZERO_CHECK
bool regenerate = !mf->IsOn("CMAKE_SUPPRESS_REGENERATION");
- if (regenerate) {
+ bool generateTopLevelProjectOnly =
+ mf->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY");
+ bool isTopLevel =
+ !root->GetStateSnapshot().GetBuildsystemDirectoryParent().IsValid();
+ if (regenerate && (isTopLevel || !generateTopLevelProjectOnly)) {
this->CreateReRunCMakeFile(root, gens);
std::string file =
this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str());
cmSystemTools::ReplaceString(file, "\\ ", " ");
- cmTarget* check =
- mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends,
- no_working_directory, "make", "-f", file.c_str());
+ cmTarget* check = mf->AddUtilityCommand(
+ CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator,
+ true, no_depends, no_working_directory, "make", "-f", file.c_str());
cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root);
root->AddGeneratorTarget(checkGt);
@@ -442,8 +483,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
continue;
}
- const std::vector<cmGeneratorTarget*>& tgts = gen->GetGeneratorTargets();
- for (auto target : tgts) {
+ for (auto target : gen->GetGeneratorTargets()) {
if (target->GetType() == cmStateEnums::GLOBAL_TARGET) {
continue;
}
@@ -479,12 +519,6 @@ void cmGlobalXCodeGenerator::AddExtraTargets(
!target->GetPropertyAsBool("EXCLUDE_FROM_ALL")) {
allbuild->AddUtility(target->GetName());
}
-
- // Refer to the build configuration file for easy editing.
- listfile = gen->GetCurrentSourceDirectory();
- listfile += "/";
- listfile += "CMakeLists.txt";
- target->AddSource(listfile);
}
}
}
@@ -512,14 +546,14 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
makefileStream.SetCopyIfDifferent(true);
makefileStream << "# Generated by CMake, DO NOT EDIT\n\n";
+ makefileStream << "TARGETS:= \n";
makefileStream << "empty:= \n";
makefileStream << "space:= $(empty) $(empty)\n";
makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n";
- for (std::vector<std::string>::const_iterator i = lfiles.begin();
- i != lfiles.end(); ++i) {
+ for (const auto& lfile : lfiles) {
makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard "
- << this->ConvertToRelativeForMake(i->c_str()) << "))\n";
+ << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n";
}
std::string checkCache = root->GetBinaryDirectory();
@@ -647,9 +681,56 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFileFromPath(
return buildFile;
}
+class XCodeGeneratorExpressionInterpreter
+ : public cmGeneratorExpressionInterpreter
+{
+ CM_DISABLE_COPY(XCodeGeneratorExpressionInterpreter)
+
+public:
+ XCodeGeneratorExpressionInterpreter(cmSourceFile* sourceFile,
+ cmLocalGenerator* localGenerator,
+ cmGeneratorTarget* generatorTarget,
+ const std::string& lang)
+ : cmGeneratorExpressionInterpreter(localGenerator, generatorTarget,
+ "NO-PER-CONFIG-SUPPORT-IN-XCODE",
+ generatorTarget->GetName(), lang)
+ , SourceFile(sourceFile)
+ {
+ }
+
+ using cmGeneratorExpressionInterpreter::Evaluate;
+
+ const char* Evaluate(const char* expression, const std::string& property)
+ {
+ const char* processed =
+ this->cmGeneratorExpressionInterpreter::Evaluate(expression, property);
+ if (this->GetCompiledGeneratorExpression()
+ .GetHadContextSensitiveCondition()) {
+ std::ostringstream e;
+ /* clang-format off */
+ e <<
+ "Xcode does not support per-config per-source " << property << ":\n"
+ " " << expression << "\n"
+ "specified for source:\n"
+ " " << this->SourceFile->GetFullPath() << "\n";
+ /* clang-format on */
+ this->GetLocalGenerator()->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
+
+ return processed;
+ }
+
+private:
+ cmSourceFile* SourceFile = nullptr;
+};
+
cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
cmLocalGenerator* lg, cmSourceFile* sf, cmGeneratorTarget* gtgt)
{
+ std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+
+ XCodeGeneratorExpressionInterpreter genexInterpreter(sf, lg, gtgt, lang);
+
// Add flags from target and source file properties.
std::string flags;
const char* srcfmt = sf->GetProperty("Fortran_FORMAT");
@@ -663,31 +744,24 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
default:
break;
}
- if (const char* cflags = sf->GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- std::string configName = "NO-PER-CONFIG-SUPPORT-IN-XCODE";
- std::unique_ptr<cmCompiledGeneratorExpression> compiledExpr =
- ge.Parse(cflags);
- const char* processed =
- compiledExpr->Evaluate(lg, configName, false, gtgt);
- if (compiledExpr->GetHadContextSensitiveCondition()) {
- std::ostringstream e;
- /* clang-format off */
- e <<
- "Xcode does not support per-config per-source COMPILE_FLAGS:\n"
- " " << cflags << "\n"
- "specified for source:\n"
- " " << sf->GetFullPath() << "\n";
- /* clang-format on */
- lg->IssueMessage(cmake::FATAL_ERROR, e.str());
- }
- lg->AppendFlags(flags, processed);
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) {
+ lg->AppendFlags(flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
// Add per-source definitions.
BuildObjectListOrString flagsBuild(this, false);
- this->AppendDefines(flagsBuild, sf->GetProperty("COMPILE_DEFINITIONS"),
- true);
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* compile_defs = sf->GetProperty(COMPILE_DEFINITIONS)) {
+ this->AppendDefines(
+ flagsBuild, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS),
+ true);
+ }
if (!flagsBuild.IsEmpty()) {
if (!flags.empty()) {
flags += ' ';
@@ -695,7 +769,15 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
flags += flagsBuild.GetString();
}
- std::string lang = this->CurrentLocalGenerator->GetSourceFileLanguage(*sf);
+ // Add per-source include directories.
+ std::vector<std::string> includes;
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = sf->GetProperty(INCLUDE_DIRECTORIES)) {
+ lg->AppendIncludeDirectories(
+ includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
+ *sf);
+ }
+ lg->AppendFlags(flags, lg->GetIncludeFlags(includes, gtgt, lang, true));
cmXCodeObject* buildFile =
this->CreateXCodeSourceFileFromPath(sf->GetFullPath(), gtgt, lang, sf);
@@ -728,9 +810,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile(
cmSystemTools::ExpandListArgument(extraFileAttributes, attributes);
// Store the attributes.
- for (std::vector<std::string>::const_iterator ai = attributes.begin();
- ai != attributes.end(); ++ai) {
- attrs->AddObject(this->CreateString(*ai));
+ for (const auto& attribute : attributes) {
+ attrs->AddObject(this->CreateString(attribute));
}
}
@@ -925,12 +1006,10 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets)
{
this->SetCurrentLocalGenerator(gen);
- const std::vector<cmGeneratorTarget*>& tgts =
- this->CurrentLocalGenerator->GetGeneratorTargets();
typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets>
cmSortedTargets;
cmSortedTargets sortedTargets;
- for (auto tgt : tgts) {
+ for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) {
sortedTargets[tgt->GetName()] = tgt;
}
for (auto& sortedTarget : sortedTargets) {
@@ -962,6 +1041,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
if (!gtgt->GetConfigCommonSourceFiles(classes)) {
return false;
}
+
+ // Add CMakeLists.txt file for user convenience.
+ std::string listfile =
+ gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+ listfile += "/CMakeLists.txt";
+ classes.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+
std::sort(classes.begin(), classes.end(), cmSourceFilePathCompare());
gtgt->ComputeObjectMapping();
@@ -970,21 +1056,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
std::vector<cmXCodeObject*> headerFiles;
std::vector<cmXCodeObject*> resourceFiles;
std::vector<cmXCodeObject*> sourceFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- cmXCodeObject* xsf =
- this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt);
+ for (auto sourceFile : classes) {
+ cmXCodeObject* xsf = this->CreateXCodeSourceFile(
+ this->CurrentLocalGenerator, sourceFile, gtgt);
cmXCodeObject* fr = xsf->GetObject("fileRef");
cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType");
cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
+ gtgt->GetTargetSourceFileFlags(sourceFile);
if (filetype && filetype->GetString() == "compiled.mach-o.objfile") {
- if ((*i)->GetObjectLibrary().empty()) {
+ if (sourceFile->GetObjectLibrary().empty()) {
externalObjFiles.push_back(xsf);
}
- } else if (this->IsHeaderFile(*i) ||
+ } else if (this->IsHeaderFile(sourceFile) ||
(tsFlags.Type ==
cmGeneratorTarget::SourceFileTypePrivateHeader) ||
(tsFlags.Type ==
@@ -992,12 +1077,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
headerFiles.push_back(xsf);
} else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) {
resourceFiles.push_back(xsf);
- } else if (!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY")) {
+ } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) {
// Include this file in the build if it has a known language
// and has not been listed as an ignored extension for this
// generator.
- if (!this->CurrentLocalGenerator->GetSourceFileLanguage(**i).empty() &&
- !this->IgnoreFile((*i)->GetExtension().c_str())) {
+ if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile)
+ .empty() &&
+ !this->IgnoreFile(sourceFile->GetExtension().c_str())) {
sourceFiles.push_back(xsf);
}
}
@@ -1009,12 +1095,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
// within the target.)
std::vector<cmSourceFile const*> objs;
gtgt->GetExternalObjects(objs, "");
- for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
- oi != objs.end(); ++oi) {
- if ((*oi)->GetObjectLibrary().empty()) {
+ for (auto sourceFile : objs) {
+ if (sourceFile->GetObjectLibrary().empty()) {
continue;
}
- std::string const& obj = (*oi)->GetFullPath();
+ std::string const& obj = sourceFile->GetFullPath();
cmXCodeObject* xsf =
this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr);
externalObjFiles.push_back(xsf);
@@ -1087,16 +1172,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
typedef std::map<std::string, std::vector<cmSourceFile*>>
mapOfVectorOfSourceFiles;
mapOfVectorOfSourceFiles bundleFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
+ for (auto sourceFile : classes) {
cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
+ gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
}
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
+ for (auto keySources : bundleFiles) {
cmXCodeObject* copyFilesBuildPhase =
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
copyFilesBuildPhase->SetComment("Copy files");
@@ -1107,13 +1190,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
std::ostringstream ostr;
if (gtgt->IsFrameworkOnApple()) {
// dstPath in frameworks is relative to Versions/<version>
- ostr << mit->first;
- } else if (mit->first != "MacOS") {
- if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) {
- ostr << mit->first;
+ ostr << keySources.first;
+ } else if (keySources.first != "MacOS") {
+ if (gtgt->Target->GetMakefile()->PlatformIsAppleEmbedded()) {
+ ostr << keySources.first;
} else {
// dstPath in bundles is relative to Contents/MacOS
- ostr << "../" << mit->first;
+ ostr << "../" << keySources.first;
}
}
copyFilesBuildPhase->AddAttribute("dstPath",
@@ -1122,10 +1205,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
copyFilesBuildPhase->AddAttribute("files", buildFiles);
- std::vector<cmSourceFile*>::iterator sfIt;
- for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
+ for (auto sourceFile : keySources.second) {
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, gtgt);
+ this->CurrentLocalGenerator, sourceFile, gtgt);
buildFiles->AddObject(xsf);
}
contentBuildPhases.push_back(copyFilesBuildPhase);
@@ -1138,16 +1220,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
typedef std::map<std::string, std::vector<cmSourceFile*>>
mapOfVectorOfSourceFiles;
mapOfVectorOfSourceFiles bundleFiles;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
+ for (auto sourceFile : classes) {
cmGeneratorTarget::SourceFileFlags tsFlags =
- gtgt->GetTargetSourceFileFlags(*i);
+ gtgt->GetTargetSourceFileFlags(sourceFile);
if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) {
- bundleFiles[tsFlags.MacFolder].push_back(*i);
+ bundleFiles[tsFlags.MacFolder].push_back(sourceFile);
}
}
- mapOfVectorOfSourceFiles::iterator mit;
- for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) {
+ for (auto keySources : bundleFiles) {
cmXCodeObject* copyFilesBuildPhase =
this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase);
copyFilesBuildPhase->SetComment("Copy files");
@@ -1155,16 +1235,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
this->CreateString("2147483647"));
copyFilesBuildPhase->AddAttribute("dstSubfolderSpec",
this->CreateString("7"));
- copyFilesBuildPhase->AddAttribute("dstPath",
- this->CreateString(mit->first));
+ copyFilesBuildPhase->AddAttribute(
+ "dstPath", this->CreateString(keySources.first));
copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing",
this->CreateString("0"));
buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
copyFilesBuildPhase->AddAttribute("files", buildFiles);
- std::vector<cmSourceFile*>::iterator sfIt;
- for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) {
+ for (auto sourceFile : keySources.second) {
cmXCodeObject* xsf = this->CreateXCodeSourceFile(
- this->CurrentLocalGenerator, *sfIt, gtgt);
+ this->CurrentLocalGenerator, sourceFile, gtgt);
buildFiles->AddObject(xsf);
}
contentBuildPhases.push_back(copyFilesBuildPhase);
@@ -1203,11 +1282,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets(
void cmGlobalXCodeGenerator::ForceLinkerLanguages()
{
- for (auto& localGenerator : this->LocalGenerators) {
- const std::vector<cmGeneratorTarget*>& tgts =
- localGenerator->GetGeneratorTargets();
+ for (auto localGenerator : this->LocalGenerators) {
// All targets depend on the build-system check target.
- for (auto tgt : tgts) {
+ for (auto tgt : localGenerator->GetGeneratorTargets()) {
// This makes sure all targets link using the proper language.
this->ForceLinkerLanguage(tgt);
}
@@ -1229,8 +1306,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
}
// If the language is compiled as a source trust Xcode to link with it.
- cmLinkImplementation const* impl = gtgt->GetLinkImplementation("NOCONFIG");
- for (auto const& Language : impl->Languages) {
+ for (auto const& Language :
+ gtgt->GetLinkImplementation("NOCONFIG")->Languages) {
if (Language == llang) {
return;
}
@@ -1330,10 +1407,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
}
// add all the sources
std::vector<cmCustomCommand> commands;
- for (std::vector<cmSourceFile*>::const_iterator i = classes.begin();
- i != classes.end(); ++i) {
- if ((*i)->GetCustomCommand()) {
- commands.push_back(*(*i)->GetCustomCommand());
+ for (auto sourceFile : classes) {
+ if (sourceFile->GetCustomCommand()) {
+ commands.push_back(*sourceFile->GetCustomCommand());
}
}
// create prebuild phase
@@ -1365,10 +1441,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
if (resourceBuildPhase) {
buildPhases->AddObject(resourceBuildPhase);
}
- std::vector<cmXCodeObject*>::iterator cit;
- for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end();
- ++cit) {
- buildPhases->AddObject(*cit);
+ for (auto obj : contentBuildPhases) {
+ buildPhases->AddObject(obj);
}
if (sourceBuildPhase) {
buildPhases->AddObject(sourceBuildPhase);
@@ -1491,12 +1565,9 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
makefile += name;
makefile += ".make";
- for (std::vector<std::string>::const_iterator currentConfig =
- this->CurrentConfigurationTypes.begin();
- currentConfig != this->CurrentConfigurationTypes.end();
- currentConfig++) {
+ for (const auto& currentConfig : this->CurrentConfigurationTypes) {
this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
- *currentConfig);
+ currentConfig);
}
std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
@@ -1652,6 +1723,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
gtgt->GetName().c_str());
return;
}
+ std::string const& langForPreprocessor = llang;
if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
@@ -1672,7 +1744,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
this->AppendDefines(ppDefs, exportMacro);
}
std::vector<std::string> targetDefines;
- gtgt->GetCompileDefinitions(targetDefines, configName, "C");
+ if (!langForPreprocessor.empty()) {
+ gtgt->GetCompileDefinitions(targetDefines, configName,
+ langForPreprocessor);
+ }
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute("GCC_PREPROCESSOR_DEFINITIONS",
ppDefs.CreateList());
@@ -1945,8 +2020,10 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
const bool emitSystemIncludes = this->XcodeVersion >= 83;
std::vector<std::string> includes;
- this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt, "C",
- configName);
+ if (!langForPreprocessor.empty()) {
+ this->CurrentLocalGenerator->GetIncludeDirectories(
+ includes, gtgt, langForPreprocessor, configName);
+ }
std::set<std::string> emitted;
emitted.insert("/System/Library/Frameworks");
@@ -1958,7 +2035,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
if (emitted.insert(frameworkDir).second) {
std::string incpath = this->XCodeEscapePath(frameworkDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(frameworkDir, configName)) {
+ gtgt->IsSystemIncludeDirectory(frameworkDir, configName,
+ langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -1967,7 +2045,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
} else {
std::string incpath = this->XCodeEscapePath(include);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(include, configName)) {
+ gtgt->IsSystemIncludeDirectory(include, configName,
+ langForPreprocessor)) {
sysdirs.Add(incpath);
} else {
dirs.Add(incpath);
@@ -1976,12 +2055,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
}
// Add framework search paths needed for linking.
if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) {
- std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths();
- for (auto const& fwDir : fwDirs) {
+ for (auto const& fwDir : cli->GetFrameworkPaths()) {
if (emitted.insert(fwDir).second) {
std::string incpath = this->XCodeEscapePath(fwDir);
if (emitSystemIncludes &&
- gtgt->IsSystemIncludeDirectory(fwDir, configName)) {
+ gtgt->IsSystemIncludeDirectory(fwDir, configName,
+ langForPreprocessor)) {
sysfdirs.Add(incpath);
} else {
fdirs.Add(incpath);
@@ -2142,9 +2221,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// runpath dirs needs to be unique to prevent corruption
std::set<std::string> unique_dirs;
- for (std::vector<std::string>::const_iterator i = runtimeDirs.begin();
- i != runtimeDirs.end(); ++i) {
- std::string runpath = *i;
+ for (auto runpath : runtimeDirs) {
runpath = this->ExpandCFGIntDir(runpath, configName);
if (unique_dirs.find(runpath) == unique_dirs.end()) {
@@ -2204,8 +2281,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
// put this last so it can override existing settings
// Convert "XCODE_ATTRIBUTE_*" properties directly.
{
- std::vector<std::string> const& props = gtgt->GetPropertyKeys();
- for (auto const& prop : props) {
+ for (auto const& prop : gtgt->GetPropertyKeys()) {
if (prop.find("XCODE_ATTRIBUTE_") == 0) {
std::string attribute = prop.substr(16);
this->FilterConfigurationAttribute(configName, attribute);
@@ -2259,16 +2335,22 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
this->XCodeObjectMap[gtgt] = target;
// Add source files without build rules for editing convenience.
- if (gtgt->GetType() == cmStateEnums::UTILITY) {
+ if (gtgt->GetType() == cmStateEnums::UTILITY &&
+ gtgt->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
std::vector<cmSourceFile*> sources;
if (!gtgt->GetConfigCommonSourceFiles(sources)) {
return nullptr;
}
- for (std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i) {
- if (!(*i)->GetPropertyAsBool("GENERATED")) {
- this->CreateXCodeFileReference(*i, gtgt);
+ // Add CMakeLists.txt file for user convenience.
+ std::string listfile =
+ gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+ listfile += "/CMakeLists.txt";
+ sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile));
+
+ for (auto sourceFile : sources) {
+ if (!sourceFile->GetPropertyAsBool("GENERATED")) {
+ this->CreateXCodeFileReference(sourceFile, gtgt);
}
}
}
@@ -2537,17 +2619,10 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute(
target->GetObject("buildConfigurationList")->GetObject();
cmXCodeObject* buildConfigs =
configurationList->GetObject("buildConfigurations");
- std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList();
- // each configuration and the target itself has a buildSettings in it
- // list.push_back(target);
- for (auto& i : list) {
- if (!configName.empty()) {
- if (i->GetObject("name")->GetString() == configName) {
- cmXCodeObject* settings = i->GetObject("buildSettings");
- this->AppendOrAddBuildSetting(settings, attribute, value);
- }
- } else {
- cmXCodeObject* settings = i->GetObject("buildSettings");
+ for (auto obj : buildConfigs->GetObjectList()) {
+ if (configName.empty() ||
+ obj->GetObject("name")->GetString() == configName) {
+ cmXCodeObject* settings = obj->GetObject("buildSettings");
this->AppendOrAddBuildSetting(settings, attribute, value);
}
}
@@ -2565,8 +2640,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
}
// Add dependencies on other CMake targets.
- TargetDependSet const& deps = this->GetTargetDirectDepends(gt);
- for (auto dep : deps) {
+ for (const auto& dep : this->GetTargetDirectDepends(gt)) {
if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) {
this->AddDependTarget(target, dptarget);
}
@@ -2581,14 +2655,13 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
const char* sep = "";
std::vector<cmSourceFile const*> objs;
gt->GetExternalObjects(objs, configName);
- for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin();
- oi != objs.end(); ++oi) {
- if ((*oi)->GetObjectLibrary().empty()) {
+ for (auto sourceFile : objs) {
+ if (sourceFile->GetObjectLibrary().empty()) {
continue;
}
linkObjs += sep;
sep = " ";
- linkObjs += this->XCodeEscapePath((*oi)->GetFullPath());
+ linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath());
}
this->AppendBuildSettingAttribute(
target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName);
@@ -2608,18 +2681,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
cmComputeLinkInformation& cli = *pcli;
// Add dependencies directly on library files.
- {
- std::vector<std::string> const& libDeps = cli.GetDepends();
- for (auto const& libDep : libDeps) {
- target->AddDependLibrary(configName, libDep);
- }
+ for (auto const& libDep : cli.GetDepends()) {
+ target->AddDependLibrary(configName, libDep);
}
// add the library search paths
{
- std::vector<std::string> const& libDirs = cli.GetDirectories();
std::string linkDirs;
- for (auto const& libDir : libDirs) {
+ for (auto const& libDir : cli.GetDirectories()) {
if (!libDir.empty() && libDir != "/usr/lib") {
// Now add the same one but append
// $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it:
@@ -2638,9 +2707,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
{
std::string linkLibs;
const char* sep = "";
- typedef cmComputeLinkInformation::ItemVector ItemVector;
- ItemVector const& libNames = cli.GetItems();
- for (auto const& libName : libNames) {
+ for (auto const& libName : cli.GetItems()) {
linkLibs += sep;
sep = " ";
if (libName.IsPath) {
@@ -2666,11 +2733,9 @@ bool cmGlobalXCodeGenerator::CreateGroups(
for (auto& generator : generators) {
cmMakefile* mf = generator->GetMakefile();
std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups();
- const std::vector<cmGeneratorTarget*>& tgts =
- generator->GetGeneratorTargets();
- for (auto gtgt : tgts) {
+ for (auto gtgt : generator->GetGeneratorTargets()) {
// Same skipping logic here as in CreateXCodeTargets so that we do not
- // end up with (empty anyhow) ALL_BUILD and XCODE_DEPEND_HELPER source
+ // end up with (empty anyhow) ZERO_CHECK, install, or test source
// groups:
//
if (gtgt->GetType() == cmStateEnums::GLOBAL_TARGET) {
@@ -2679,6 +2744,9 @@ bool cmGlobalXCodeGenerator::CreateGroups(
if (gtgt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
+ if (gtgt->GetName() == CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ continue;
+ }
// add the soon to be generated Info.plist file as a source for a
// MACOSX_BUNDLE file
@@ -2688,11 +2756,8 @@ bool cmGlobalXCodeGenerator::CreateGroups(
gtgt->AddSource(plist);
}
- std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
- gtgt->GetAllConfigSources();
-
// Put cmSourceFile instances in proper groups:
- for (auto const& si : sources) {
+ for (auto const& si : gtgt->GetAllConfigSources()) {
cmSourceFile const* sf = si.Source;
if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) {
// Object library files go on the link line instead.
@@ -2706,6 +2771,20 @@ bool cmGlobalXCodeGenerator::CreateGroups(
std::string key = GetGroupMapKeyFromPath(gtgt, source);
this->GroupMap[key] = pbxgroup;
}
+
+ // Add CMakeLists.txt file for user convenience.
+ {
+ std::string listfile =
+ gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
+ listfile += "/CMakeLists.txt";
+ cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile);
+ std::string const& source = sf->GetFullPath();
+ cmSourceGroup* sourceGroup =
+ mf->FindSourceGroup(source.c_str(), sourceGroups);
+ cmXCodeObject* pbxgroup = this->CreateOrGetPBXGroup(gtgt, sourceGroup);
+ std::string key = GetGroupMapKeyFromPath(gtgt, source);
+ this->GroupMap[key] = pbxgroup;
+ }
}
}
return true;
@@ -2780,18 +2859,17 @@ 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())) {
- std::vector<std::string> folders =
- cmSystemTools::tokenize(sg->GetFullName(), "\\");
+ if (sg->GetFullName() != sg->GetName()) {
std::string curr_folder = target;
curr_folder += "/";
- for (auto const& folder : folders) {
+ for (auto const& folder :
+ cmSystemTools::tokenize(sg->GetFullName(), "\\")) {
curr_folder += folder;
std::map<std::string, cmXCodeObject*>::iterator i_folder =
this->GroupNameMap.find(curr_folder);
@@ -2896,10 +2974,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
this->CreateObject(cmXCodeObject::OBJECT_LIST);
typedef std::vector<std::pair<std::string, cmXCodeObject*>> Configs;
Configs configs;
- const char* defaultConfigName = "Debug";
- for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) {
- const char* name = this->CurrentConfigurationTypes[i].c_str();
- if (0 == i) {
+ std::string defaultConfigName;
+ for (const auto& name : this->CurrentConfigurationTypes) {
+ if (defaultConfigName.empty()) {
defaultConfigName = name;
}
cmXCodeObject* config =
@@ -2907,6 +2984,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
config->AddAttribute("name", this->CreateString(name));
configs.push_back(std::make_pair(name, config));
}
+ if (defaultConfigName.empty()) {
+ defaultConfigName = "Debug";
+ }
for (auto& config : configs) {
buildConfigurations->AddObject(config.second);
}
@@ -2941,7 +3021,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
buildSettings->AddAttribute("ARCHS", this->CreateString(archs));
}
if (deploymentTarget && *deploymentTarget) {
- buildSettings->AddAttribute("MACOSX_DEPLOYMENT_TARGET",
+ buildSettings->AddAttribute(GetDeploymentPlatform(root->GetMakefile()),
this->CreateString(deploymentTarget));
}
if (!this->GeneratorToolset.empty()) {
@@ -2971,16 +3051,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
// Put this last so it can override existing settings
// Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly.
- std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions();
- for (std::vector<std::string>::const_iterator d = vars.begin();
- d != vars.end(); ++d) {
- if (d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
- std::string attribute = d->substr(22);
+ for (const auto& var : this->CurrentMakefile->GetDefinitions()) {
+ if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) {
+ std::string attribute = var.substr(22);
this->FilterConfigurationAttribute(config.first, attribute);
if (!attribute.empty()) {
cmGeneratorExpression ge;
std::string processed =
- ge.Parse(this->CurrentMakefile->GetDefinition(*d))
+ ge.Parse(this->CurrentMakefile->GetDefinition(var))
->Evaluate(this->CurrentLocalGenerator, config.first);
buildSettingsForCfg->AddAttribute(attribute,
this->CreateString(processed));
@@ -3096,10 +3174,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
"# link. This forces Xcode to relink the targets from scratch. It\n"
"# does not seem to check these dependencies itself.\n";
/* clang-format on */
- for (std::vector<std::string>::const_iterator ct =
- this->CurrentConfigurationTypes.begin();
- ct != this->CurrentConfigurationTypes.end(); ++ct) {
- std::string configName = *ct;
+ for (const auto& configName : this->CurrentConfigurationTypes) {
for (auto target : targets) {
cmGeneratorTarget* gt = target->GetTarget();
@@ -3109,7 +3184,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
gt->GetType() == cmStateEnums::SHARED_LIBRARY ||
gt->GetType() == cmStateEnums::MODULE_LIBRARY) {
// Declare an entry point for the target post-build phase.
- makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct)
+ makefileStream << this->PostBuildMakeTarget(gt->GetName(), configName)
<< ":\n";
}
@@ -3122,21 +3197,19 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// Add this target to the post-build phases of its dependencies.
std::map<std::string, cmXCodeObject::StringVec>::const_iterator y =
- target->GetDependTargets().find(*ct);
+ target->GetDependTargets().find(configName);
if (y != target->GetDependTargets().end()) {
- std::vector<std::string> const& deptgts = y->second;
- for (auto const& deptgt : deptgts) {
- makefileStream << this->PostBuildMakeTarget(deptgt, *ct) << ": "
- << trel << "\n";
+ for (auto const& deptgt : y->second) {
+ makefileStream << this->PostBuildMakeTarget(deptgt, configName)
+ << ": " << trel << "\n";
}
}
std::vector<cmGeneratorTarget*> objlibs;
gt->GetObjectLibrariesCMP0026(objlibs);
- for (std::vector<cmGeneratorTarget*>::const_iterator it =
- objlibs.begin();
- it != objlibs.end(); ++it) {
- makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct)
+ for (auto objLib : objlibs) {
+ makefileStream << this->PostBuildMakeTarget(objLib->GetName(),
+ configName)
<< ": " << trel << "\n";
}
@@ -3145,23 +3218,20 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
// List dependencies if any exist.
std::map<std::string, cmXCodeObject::StringVec>::const_iterator x =
- target->GetDependLibraries().find(*ct);
+ target->GetDependLibraries().find(configName);
if (x != target->GetDependLibraries().end()) {
- std::vector<std::string> const& deplibs = x->second;
- for (auto const& deplib : deplibs) {
+ for (auto const& deplib : x->second) {
std::string file = this->ConvertToRelativeForMake(deplib.c_str());
makefileStream << "\\\n\t" << file;
dummyRules.insert(file);
}
}
- for (std::vector<cmGeneratorTarget*>::const_iterator it =
- objlibs.begin();
- it != objlibs.end(); ++it) {
+ for (auto objLib : objlibs) {
- const std::string objLibName = (*it)->GetName();
+ const std::string objLibName = objLib->GetName();
std::string d = this->GetObjectsNormalDirectory(this->CurrentProject,
- configName, *it);
+ configName, objLib);
d += "lib";
d += objLibName;
d += ".a";
@@ -3177,11 +3247,11 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
<< this->ConvertToRelativeForMake(tfull.c_str())
<< "\n";
// if building for more than one architecture
- // then remove those exectuables as well
+ // then remove those executables as well
if (this->Architectures.size() > 1) {
std::string universal = this->GetObjectsNormalDirectory(
this->CurrentProject, configName, gt);
- for (auto& architecture : this->Architectures) {
+ for (const auto& architecture : this->Architectures) {
std::string universalFile = universal;
universalFile += architecture;
universalFile += "/";
@@ -3212,7 +3282,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
return;
}
// Skip local generators that are excluded from this project.
- for (auto& generator : generators) {
+ for (auto generator : generators) {
if (this->IsExcluded(root, generator)) {
continue;
}
@@ -3234,9 +3304,9 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
}
this->WriteXCodePBXProj(fout, root, generators);
- // Since the lowest available Xcode version for testing was 7.0,
+ // Since the lowest available Xcode version for testing was 6.4,
// I'm setting this as a limit then
- if (this->XcodeVersion >= 70) {
+ if (this->XcodeVersion >= 64) {
if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() ||
root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) {
this->OutputXCodeSharedSchemes(xcodeDir);
@@ -3258,10 +3328,7 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
// collect all tests for the targets
std::map<std::string, cmXCodeScheme::TestObjects> testables;
- for (std::vector<cmXCodeObject*>::const_iterator i =
- this->XCodeObjects.begin();
- i != this->XCodeObjects.end(); ++i) {
- cmXCodeObject* obj = *i;
+ for (auto obj : this->XCodeObjects) {
if (obj->GetType() != cmXCodeObject::OBJECT ||
obj->GetIsA() != cmXCodeObject::PBXNativeTarget) {
continue;
@@ -3280,10 +3347,7 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
}
// generate scheme
- for (std::vector<cmXCodeObject*>::const_iterator i =
- this->XCodeObjects.begin();
- i != this->XCodeObjects.end(); ++i) {
- cmXCodeObject* obj = *i;
+ for (auto obj : this->XCodeObjects) {
if (obj->GetType() == cmXCodeObject::OBJECT &&
(obj->GetIsA() == cmXCodeObject::PBXNativeTarget ||
obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) {
@@ -3386,7 +3450,8 @@ void cmGlobalXCodeGenerator::GetDocumentation(cmDocumentationEntry& entry)
entry.Brief = "Generate Xcode project files.";
}
-std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(const char* p)
+std::string cmGlobalXCodeGenerator::ConvertToRelativeForMake(
+ std::string const& p)
{
return cmSystemTools::ConvertToOutputPath(p);
}
@@ -3480,7 +3545,7 @@ void cmGlobalXCodeGenerator::AppendDefines(
}
void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
- std::string const& flag)
+ std::string const& flag) const
{
// Short-circuit for an empty flag.
if (flag.empty()) {
@@ -3512,17 +3577,17 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
}
// Flag value with escaped quotes and backslashes.
- for (const char* c = flag.c_str(); *c; ++c) {
- if (*c == '\'') {
+ for (auto c : flag) {
+ if (c == '\'') {
if (this->XcodeVersion >= 40) {
flags += "'\\''";
} else {
flags += "\\'";
}
- } else if (*c == '\\') {
+ } else if (c == '\\') {
flags += "\\\\";
} else {
- flags += *c;
+ flags += c;
}
}
@@ -3570,7 +3635,7 @@ bool cmGlobalXCodeGenerator::UseEffectivePlatformName(cmMakefile* mf) const
"XCODE_EMIT_EFFECTIVE_PLATFORM_NAME");
if (!epnValue) {
- return mf->PlatformIsAppleIos();
+ return mf->PlatformIsAppleEmbedded();
}
return cmSystemTools::IsOn(epnValue);
@@ -3592,3 +3657,24 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
dir += "/";
gt->ObjectDirectory = dir;
}
+
+std::string cmGlobalXCodeGenerator::GetDeploymentPlatform(const cmMakefile* mf)
+{
+ switch (mf->GetAppleSDKType()) {
+ case cmMakefile::AppleSDK::AppleTVOS:
+ case cmMakefile::AppleSDK::AppleTVSimulator:
+ return "TVOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::IPhoneOS:
+ case cmMakefile::AppleSDK::IPhoneSimulator:
+ return "IPHONEOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::WatchOS:
+ case cmMakefile::AppleSDK::WatchSimulator:
+ return "WATCHOS_DEPLOYMENT_TARGET";
+
+ case cmMakefile::AppleSDK::MacOS:
+ default:
+ return "MACOSX_DEPLOYMENT_TARGET";
+ }
+}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index e9ca91ce4..b45887e37 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -55,6 +55,13 @@ public:
*/
void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
bool optional) override;
+
+ /**
+ * Open a generated IDE project given the following information.
+ */
+ bool Open(const std::string& bindir, const std::string& projectName,
+ bool dryRun) override;
+
/**
* Try running cmake and building a file. This is used for dynalically
* loaded commands, not as part of the usual build process.
@@ -97,7 +104,7 @@ public:
bool ShouldStripResourcePath(cmMakefile*) const override;
bool SetGeneratorToolset(std::string const& ts, cmMakefile* mf) override;
- void AppendFlag(std::string& flags, std::string const& flag);
+ void AppendFlag(std::string& flags, std::string const& flag) const;
protected:
void AddExtraIDETargets() override;
@@ -112,7 +119,7 @@ private:
std::string XCodeEscapePath(const std::string& p);
std::string RelativeToSource(const char* p);
std::string RelativeToBinary(const char* p);
- std::string ConvertToRelativeForMake(const char* p);
+ std::string ConvertToRelativeForMake(std::string const& p);
void CreateCustomCommands(cmXCodeObject* buildPhases,
cmXCodeObject* sourceBuildPhase,
cmXCodeObject* headerBuildPhase,
@@ -247,6 +254,8 @@ private:
const std::string& configName,
const cmGeneratorTarget* t) const;
+ static std::string GetDeploymentPlatform(const cmMakefile* mf);
+
void ComputeArchitectures(cmMakefile* mf);
void ComputeObjectDirArch(cmMakefile* mf);
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index e684f5ec2..1bbfbe03f 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -224,11 +224,11 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName,
ignoreTargetsRegExVector);
for (std::string const& currentRegexString : ignoreTargetsRegExVector) {
cmsys::RegularExpression currentRegex;
- if (!currentRegex.compile(currentRegexString.c_str())) {
+ if (!currentRegex.compile(currentRegexString)) {
std::cerr << "Could not compile bad regex \"" << currentRegexString
<< "\"" << std::endl;
}
- this->TargetsToIgnoreRegex.push_back(currentRegex);
+ this->TargetsToIgnoreRegex.push_back(std::move(currentRegex));
}
}
}
diff --git a/Source/cmIDEOptions.cxx b/Source/cmIDEOptions.cxx
index 5e872d2ff..354b757c8 100644
--- a/Source/cmIDEOptions.cxx
+++ b/Source/cmIDEOptions.cxx
@@ -13,6 +13,7 @@ cmIDEOptions::cmIDEOptions()
{
this->DoingDefine = false;
this->AllowDefine = true;
+ this->DoingInclude = false;
this->AllowSlash = false;
this->DoingFollowing = 0;
for (int i = 0; i < FlagTableCount; ++i) {
@@ -33,6 +34,13 @@ void cmIDEOptions::HandleFlag(const char* flag)
return;
}
+ // If the last option was -I then this option is the include directory.
+ if (this->DoingInclude) {
+ this->DoingInclude = false;
+ this->Includes.push_back(flag);
+ return;
+ }
+
// If the last option expected a following value, this is it.
if (this->DoingFollowing) {
this->FlagMapUpdate(this->DoingFollowing, flag);
@@ -53,6 +61,17 @@ void cmIDEOptions::HandleFlag(const char* flag)
}
return;
}
+ // Look for include directory.
+ if (this->AllowInclude && flag[1] == 'I') {
+ if (flag[2] == '\0') {
+ // The next argument will have the include directory.
+ this->DoingInclude = true;
+ } else {
+ // Store this include directory.
+ this->Includes.push_back(flag + 2);
+ }
+ return;
+ }
// Look through the available flag tables.
bool flag_handled = false;
@@ -155,12 +174,35 @@ std::vector<std::string> const& cmIDEOptions::GetDefines() const
return this->Defines;
}
-void cmIDEOptions::AddFlag(const char* flag, const char* value)
+void cmIDEOptions::AddInclude(const std::string& include)
+{
+ this->Includes.push_back(include);
+}
+
+void cmIDEOptions::AddIncludes(const char* includes)
+{
+ if (includes) {
+ // Expand the list of includes.
+ cmSystemTools::ExpandListArgument(includes, this->Includes);
+ }
+}
+void cmIDEOptions::AddIncludes(const std::vector<std::string>& includes)
+{
+ this->Includes.insert(this->Includes.end(), includes.begin(),
+ includes.end());
+}
+
+std::vector<std::string> const& cmIDEOptions::GetIncludes() const
+{
+ return this->Includes;
+}
+
+void cmIDEOptions::AddFlag(std::string const& flag, std::string const& value)
{
this->FlagMap[flag] = value;
}
-void cmIDEOptions::AddFlag(const char* flag,
+void cmIDEOptions::AddFlag(std::string const& flag,
std::vector<std::string> const& value)
{
this->FlagMap[flag] = value;
@@ -185,7 +227,7 @@ void cmIDEOptions::AppendFlagString(std::string const& flag,
this->FlagMap[flag].append_with_space(value);
}
-void cmIDEOptions::RemoveFlag(const char* flag)
+void cmIDEOptions::RemoveFlag(std::string const& flag)
{
this->FlagMap.erase(flag);
}
@@ -195,12 +237,13 @@ bool cmIDEOptions::HasFlag(std::string const& flag) const
return this->FlagMap.find(flag) != this->FlagMap.end();
}
-const char* cmIDEOptions::GetFlag(const char* flag)
+const char* cmIDEOptions::GetFlag(std::string const& flag) const
{
// This method works only for single-valued flags!
- std::map<std::string, FlagValue>::iterator i = this->FlagMap.find(flag);
- if (i != this->FlagMap.end() && i->second.size() == 1) {
+ std::map<std::string, FlagValue>::const_iterator i =
+ this->FlagMap.find(flag);
+ if (i != this->FlagMap.cend() && i->second.size() == 1) {
return i->second[0].c_str();
}
- return 0;
+ return nullptr;
}
diff --git a/Source/cmIDEOptions.h b/Source/cmIDEOptions.h
index af0312874..54cb52446 100644
--- a/Source/cmIDEOptions.h
+++ b/Source/cmIDEOptions.h
@@ -20,21 +20,26 @@ public:
cmIDEOptions();
virtual ~cmIDEOptions();
- // Store definitions and flags.
+ // Store definitions, includes and flags.
void AddDefine(const std::string& define);
void AddDefines(const char* defines);
void AddDefines(const std::vector<std::string>& defines);
std::vector<std::string> const& GetDefines() const;
- void AddFlag(const char* flag, const char* value);
- void AddFlag(const char* flag, std::vector<std::string> const& value);
+ void AddInclude(const std::string& includes);
+ void AddIncludes(const char* includes);
+ void AddIncludes(const std::vector<std::string>& includes);
+ std::vector<std::string> const& GetIncludes() const;
+
+ void AddFlag(std::string const& flag, std::string const& value);
+ void AddFlag(std::string const& flag, std::vector<std::string> const& value);
void AppendFlag(std::string const& flag, std::string const& value);
void AppendFlag(std::string const& flag,
std::vector<std::string> const& value);
void AppendFlagString(std::string const& flag, std::string const& value);
- void RemoveFlag(const char* flag);
+ void RemoveFlag(std::string const& flag);
bool HasFlag(std::string const& flag) const;
- const char* GetFlag(const char* flag);
+ const char* GetFlag(std::string const& flag) const;
protected:
// create a map of xml tags to the values they should have in the output
@@ -76,8 +81,13 @@ protected:
// Preprocessor definitions.
std::vector<std::string> Defines;
+ // Include directories.
+ std::vector<std::string> Includes;
+
bool DoingDefine;
bool AllowDefine;
+ bool DoingInclude;
+ bool AllowInclude;
bool AllowSlash;
cmIDEFlagTable const* DoingFollowing;
enum
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index cd4d85030..b42d75e1f 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -63,7 +63,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
return true;
}
- if (!cmSystemTools::FileIsFullPath(fname.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(fname)) {
// Not a path. Maybe module.
std::string module = fname;
module += ".cmake";
@@ -112,7 +112,7 @@ bool cmIncludeCommand::InitialPass(std::vector<std::string> const& args,
std::string listFile = cmSystemTools::CollapseFullPath(
fname, this->Makefile->GetCurrentSourceDirectory());
- if (optional && !cmSystemTools::FileExists(listFile.c_str())) {
+ if (optional && !cmSystemTools::FileExists(listFile)) {
if (!resultVarName.empty()) {
this->Makefile->AddDefinition(resultVarName, "NOTFOUND");
}
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 4c3060797..4f80fb85a 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -77,7 +77,7 @@ static bool StartsWithGeneratorExpression(const std::string& input)
// do a lot of cleanup on the arguments because this is one place where folks
// sometimes take the output of a program and pass it directly into this
// command not thinking that a single argument could be filled with spaces
-// and newlines etc liek below:
+// and newlines etc like below:
//
// " /foo/bar
// /boo/hoo /dingle/berry "
@@ -97,7 +97,7 @@ void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
std::string inc = arg.substr(lastPos, pos);
this->NormalizeInclude(inc);
if (!inc.empty()) {
- incs.push_back(inc);
+ incs.push_back(std::move(inc));
}
}
lastPos = pos + 1;
@@ -105,7 +105,7 @@ void cmIncludeDirectoryCommand::GetIncludes(const std::string& arg,
std::string inc = arg.substr(lastPos);
this->NormalizeInclude(inc);
if (!inc.empty()) {
- incs.push_back(inc);
+ incs.push_back(std::move(inc));
}
}
@@ -123,7 +123,7 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
if (!cmSystemTools::IsOff(inc.c_str())) {
cmSystemTools::ConvertToUnixSlashes(inc);
- if (!cmSystemTools::FileIsFullPath(inc.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(inc)) {
if (!StartsWithGeneratorExpression(inc)) {
std::string tmp = this->Makefile->GetCurrentSourceDirectory();
tmp += "/";
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index bd16b1d92..85e8cd363 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -3,6 +3,7 @@
#include "cmIncludeExternalMSProjectCommand.h"
#ifdef _WIN32
+#include "cmGlobalGenerator.h"
#include "cmMakefile.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
@@ -22,7 +23,9 @@ bool cmIncludeExternalMSProjectCommand::InitialPass(
}
// only compile this for win32 to avoid coverage errors
#ifdef _WIN32
- if (this->Makefile->GetDefinition("WIN32")) {
+ if (this->Makefile->GetDefinition("WIN32") ||
+ this->Makefile->GetGlobalGenerator()
+ ->IsIncludeExternalMSProjectSupported()) {
enum Doing
{
DoingNone,
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 685fc671c..394f976ca 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -5,6 +5,7 @@
#include "cmsys/Glob.hxx"
#include <sstream>
#include <stddef.h>
+#include <utility>
#include "cmAlgorithms.h"
#include "cmCommandArgumentsHelper.h"
@@ -154,7 +155,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
} else if (doing_script) {
doing_script = false;
std::string script = arg;
- if (!cmSystemTools::FileIsFullPath(script.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(script)) {
script = this->Makefile->GetCurrentSourceDirectory();
script += "/";
script += arg;
@@ -1044,14 +1045,14 @@ bool cmInstallCommand::HandleDirectoryMode(
// Convert this directory to a full path.
std::string dir = args[i];
std::string::size_type gpos = cmGeneratorExpression::Find(dir);
- if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir.c_str())) {
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) {
dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += args[i];
}
// Make sure the name is a directory.
- if (cmSystemTools::FileExists(dir.c_str()) &&
+ if (cmSystemTools::FileExists(dir) &&
!cmSystemTools::FileIsDirectory(dir)) {
std::ostringstream e;
e << args[0] << " given non-directory \"" << args[i]
@@ -1061,7 +1062,7 @@ bool cmInstallCommand::HandleDirectoryMode(
}
// Store the directory for installation.
- dirs.push_back(dir);
+ dirs.push_back(std::move(dir));
} else if (doing == DoingConfigurations) {
configurations.push_back(args[i]);
} else if (doing == DoingDestination) {
@@ -1133,7 +1134,7 @@ bool cmInstallCommand::HandleDirectoryMode(
// Support installing an empty directory.
if (dirs.empty() && destination) {
- dirs.push_back("");
+ dirs.emplace_back();
}
// Check if there is something to do.
@@ -1374,7 +1375,7 @@ bool cmInstallCommand::MakeFilesFullPath(
for (std::string const& relFile : relFiles) {
std::string file = relFile;
std::string::size_type gpos = cmGeneratorExpression::Find(file);
- if (gpos != 0 && !cmSystemTools::FileIsFullPath(file.c_str())) {
+ if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
file = this->Makefile->GetCurrentSourceDirectory();
file += "/";
file += relFile;
@@ -1388,7 +1389,7 @@ bool cmInstallCommand::MakeFilesFullPath(
return false;
}
// Store the file for installation.
- absFiles.push_back(file);
+ absFiles.push_back(std::move(file));
}
return true;
}
diff --git a/Source/cmInstallCommandArguments.cxx b/Source/cmInstallCommandArguments.cxx
index 12abac81b..7b79ab5c8 100644
--- a/Source/cmInstallCommandArguments.cxx
+++ b/Source/cmInstallCommandArguments.cxx
@@ -4,6 +4,8 @@
#include "cmSystemTools.h"
+#include <utility>
+
// Table of valid permissions.
const char* cmInstallCommandArguments::PermissionsTable[] = {
"OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE", "GROUP_READ",
@@ -200,6 +202,6 @@ void cmInstallCommandIncludesArgument::Parse(
for (; it != args->end(); ++it) {
std::string dir = *it;
cmSystemTools::ConvertToUnixSlashes(dir);
- this->IncludeDirs.push_back(dir);
+ this->IncludeDirs.push_back(std::move(dir));
}
}
diff --git a/Source/cmInstallDirectoryGenerator.cxx b/Source/cmInstallDirectoryGenerator.cxx
index e4209bd22..b569b731b 100644
--- a/Source/cmInstallDirectoryGenerator.cxx
+++ b/Source/cmInstallDirectoryGenerator.cxx
@@ -72,7 +72,7 @@ void cmInstallDirectoryGenerator::GenerateScriptForConfig(
// Make sure all dirs have absolute paths.
cmMakefile const& mf = *this->LocalGenerator->GetMakefile();
for (std::string& d : dirs) {
- if (!cmSystemTools::FileIsFullPath(d.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(d)) {
d = std::string(mf.GetCurrentSourceDirectory()) + "/" + d;
}
}
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index fdd231ca7..5990f3059 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -132,7 +132,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
// Create the temporary directory in which to store the files.
this->ComputeTempDir();
- cmSystemTools::MakeDirectory(this->TempDir.c_str());
+ cmSystemTools::MakeDirectory(this->TempDir);
// Construct a temporary location for the file.
this->MainImportFile = this->TempDir;
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 4a3b620af..4dde18fb0 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -30,8 +30,7 @@ bool cmInstallFilesCommand::InitialPass(std::vector<std::string> const& args,
for (std::vector<std::string>::const_iterator s = args.begin() + 2;
s != args.end(); ++s) {
// Find the source location for each file listed.
- std::string f = this->FindInstallSource(s->c_str());
- this->Files.push_back(f);
+ this->Files.push_back(this->FindInstallSource(s->c_str()));
}
this->CreateInstallGenerator();
} else {
@@ -138,11 +137,11 @@ std::string cmInstallFilesCommand::FindInstallSource(const char* name) const
ts += "/";
ts += name;
- if (cmSystemTools::FileExists(tb.c_str())) {
+ if (cmSystemTools::FileExists(tb)) {
// The file exists in the binary tree. Use it.
return tb;
}
- if (cmSystemTools::FileExists(ts.c_str())) {
+ if (cmSystemTools::FileExists(ts)) {
// The file exists in the source tree. Use it.
return ts;
}
diff --git a/Source/cmInstallGenerator.cxx b/Source/cmInstallGenerator.cxx
index 4d019782b..53ac71622 100644
--- a/Source/cmInstallGenerator.cxx
+++ b/Source/cmInstallGenerator.cxx
@@ -55,7 +55,7 @@ void cmInstallGenerator::AddInstallRule(
break;
}
os << indent;
- if (cmSystemTools::FileIsFullPath(dest.c_str())) {
+ if (cmSystemTools::FileIsFullPath(dest)) {
os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
os << indent << " \"";
for (std::vector<std::string>::const_iterator fi = files.begin();
@@ -165,7 +165,7 @@ std::string cmInstallGenerator::ConvertToAbsoluteDestination(
std::string const& dest) const
{
std::string result;
- if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest.c_str())) {
+ if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
result = "${CMAKE_INSTALL_PREFIX}/";
}
result += dest;
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 5ee81fbf6..f01a4c1c4 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -109,11 +109,11 @@ std::string cmInstallProgramsCommand::FindInstallSource(const char* name) const
ts += "/";
ts += name;
- if (cmSystemTools::FileExists(tb.c_str())) {
+ if (cmSystemTools::FileExists(tb)) {
// The file exists in the binary tree. Use it.
return tb;
}
- if (cmSystemTools::FileExists(ts.c_str())) {
+ if (cmSystemTools::FileExists(ts)) {
// The file exists in the source tree. Use it.
return ts;
}
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index b964794ed..a9b4908e5 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -132,8 +132,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
if (this->ImportLibrary) {
std::string from1 = fromDirConfig + targetNameImport;
std::string to1 = toDir + targetNameImport;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
if (this->Target->GetImplibGNUtoMS(targetNameImport,
targetNameImportLib)) {
@@ -167,7 +167,7 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
to1 += ".";
to1 += ext;
to1 += "/";
- if (!mf->PlatformIsAppleIos()) {
+ if (!mf->PlatformIsAppleEmbedded()) {
to1 += "Contents/MacOS/";
}
to1 += targetName;
@@ -176,13 +176,13 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
if (targetNameReal != targetName) {
std::string from2 = fromDirConfig + targetNameReal;
std::string to2 = toDir += targetNameReal;
- filesFrom.push_back(from2);
- filesTo.push_back(to2);
+ filesFrom.push_back(std::move(from2));
+ filesTo.push_back(std::move(to2));
}
}
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
}
} else {
std::string targetName;
@@ -198,8 +198,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
std::string from1 = fromDirConfig + targetNameImport;
std::string to1 = toDir + targetNameImport;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
std::string targetNameImportLib;
if (this->Target->GetImplibGNUtoMS(targetNameImport,
targetNameImportLib)) {
@@ -223,8 +223,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
// Tweaks apply to the binary inside the bundle.
std::string to1 = toDir + targetNameReal;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
} else if (this->Target->IsCFBundleOnApple()) {
// Install the whole app bundle directory.
type = cmInstallType_DIRECTORY;
@@ -235,8 +235,8 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
std::string from1 = fromDirConfig + targetNameBase;
std::string to1 = toDir + targetName;
- filesFrom.push_back(from1);
- filesTo.push_back(to1);
+ filesFrom.push_back(std::move(from1));
+ filesTo.push_back(std::move(to1));
} else {
bool haveNamelink = false;
@@ -796,7 +796,7 @@ void cmInstallTargetGenerator::AddUniversalInstallRule(
{
cmMakefile const* mf = this->Target->Target->GetMakefile();
- if (!mf->PlatformIsAppleIos() || !mf->IsOn("XCODE")) {
+ if (!mf->PlatformIsAppleEmbedded() || !mf->IsOn("XCODE")) {
return;
}
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index 98ab7e7b3..1371c5352 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -29,7 +29,7 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir)
{
std::string unixPath = dir;
cmSystemTools::ConvertToUnixSlashes(unixPath);
- if (!cmSystemTools::FileIsFullPath(unixPath.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(unixPath)) {
bool convertToAbsolute = false;
std::ostringstream e;
/* clang-format off */
diff --git a/Source/cmLinkedTree.h b/Source/cmLinkedTree.h
index 8865e23a1..975f05240 100644
--- a/Source/cmLinkedTree.h
+++ b/Source/cmLinkedTree.h
@@ -137,7 +137,7 @@ public:
iterator Push(iterator it) { return Push_impl(it, T()); }
- iterator Push(iterator it, T t) { return Push_impl(it, t); }
+ iterator Push(iterator it, T t) { return Push_impl(it, std::move(t)); }
bool IsLast(iterator it) { return it.Position == this->Data.size(); }
@@ -177,12 +177,12 @@ private:
T* GetPointer(PositionType pos) { return &this->Data[pos]; }
- iterator Push_impl(iterator it, T t)
+ iterator Push_impl(iterator it, T&& t)
{
assert(this->UpPositions.size() == this->Data.size());
assert(it.Position <= this->UpPositions.size());
this->UpPositions.push_back(it.Position);
- this->Data.push_back(t);
+ this->Data.push_back(std::move(t));
return iterator(this, this->UpPositions.size());
}
diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx
index 8e8a54d5f..64e634f44 100644
--- a/Source/cmListFileCache.cxx
+++ b/Source/cmListFileCache.cxx
@@ -252,8 +252,7 @@ bool cmListFileParser::ParseFunction(const char* name, long line)
bool cmListFileParser::AddArgument(cmListFileLexer_Token* token,
cmListFileArgument::Delimiter delim)
{
- cmListFileArgument a(token->text, delim, token->line);
- this->Function.Arguments.push_back(a);
+ this->Function.Arguments.emplace_back(token->text, delim, token->line);
if (this->Separation == SeparationOkay) {
return true;
}
@@ -438,6 +437,19 @@ void cmListFileBacktrace::PrintCallStack(std::ostream& out) const
}
}
+size_t cmListFileBacktrace::Depth() const
+{
+ size_t depth = 0;
+ if (this->Cur == nullptr) {
+ return 0;
+ }
+
+ for (Entry* i = this->Cur->Up; i; i = i->Up) {
+ depth++;
+ }
+ return depth;
+}
+
std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc)
{
os << lfc.FilePath;
diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h
index 349ddef91..1f9e3740e 100644
--- a/Source/cmListFileCache.h
+++ b/Source/cmListFileCache.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include <iosfwd>
+#include <stddef.h>
#include <string>
#include <vector>
@@ -138,6 +139,9 @@ public:
// Print the call stack below the top of the backtrace.
void PrintCallStack(std::ostream& out) const;
+ // Get the number of 'frames' in this backtrace
+ size_t Depth() const;
+
private:
struct Entry;
diff --git a/Source/cmLoadCacheCommand.cxx b/Source/cmLoadCacheCommand.cxx
index 32fdef51c..b1fee8dc6 100644
--- a/Source/cmLoadCacheCommand.cxx
+++ b/Source/cmLoadCacheCommand.cxx
@@ -82,7 +82,7 @@ bool cmLoadCacheCommand::ReadWithPrefix(std::vector<std::string> const& args)
// Make sure the cache file exists.
std::string cacheFile = args[0] + "/CMakeCache.txt";
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (!cmSystemTools::FileExists(cacheFile)) {
std::string e = "Cannot load cache file from " + cacheFile;
this->SetError(e);
return false;
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 50ebfa119..5a43f2e2c 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmLocalCommonGenerator.h"
+#include <utility>
#include <vector>
#include "cmGeneratorTarget.h"
@@ -76,3 +77,17 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
return flags;
}
+
+void cmLocalCommonGenerator::ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt)
+{
+ // Determine if these object files should use a custom extension
+ char const* custom_ext = gt->GetCustomObjectExtension();
+ for (auto& si : mapping) {
+ cmSourceFile const* sf = si.first;
+ bool keptSourceExtension;
+ si.second = this->GetObjectFileNameWithoutTarget(
+ *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
+ }
+}
diff --git a/Source/cmLocalCommonGenerator.h b/Source/cmLocalCommonGenerator.h
index a60573ca6..7b8e6fe8a 100644
--- a/Source/cmLocalCommonGenerator.h
+++ b/Source/cmLocalCommonGenerator.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
#include <string>
#include "cmLocalGenerator.h"
@@ -12,6 +13,7 @@
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
+class cmSourceFile;
/** \class cmLocalCommonGenerator
* \brief Common infrastructure for Makefile and Ninja local generators.
@@ -30,6 +32,10 @@ public:
std::string GetTargetFortranFlags(cmGeneratorTarget const* target,
std::string const& config) override;
+ void ComputeObjectFilenames(
+ std::map<cmSourceFile const*, std::string>& mapping,
+ cmGeneratorTarget const* gt = nullptr) override;
+
protected:
std::string WorkingDirectory;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 1a088ea9e..e942ff4d9 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -16,6 +16,7 @@
#include "cmMakefile.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
+#include "cmSourceFileLocation.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateTypes.h"
@@ -37,6 +38,7 @@
#include <sstream>
#include <stdio.h>
#include <string.h>
+#include <unordered_set>
#include <utility>
#if defined(__HAIKU__)
@@ -135,8 +137,8 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile)
this->VariableMappings[compilerOptionSysroot] =
this->Makefile->GetSafeDefinition(compilerOptionSysroot);
- for (const char* const* replaceIter = cmArrayBegin(ruleReplaceVars);
- replaceIter != cmArrayEnd(ruleReplaceVars); ++replaceIter) {
+ for (const char* const* replaceIter = cm::cbegin(ruleReplaceVars);
+ replaceIter != cm::cend(ruleReplaceVars); ++replaceIter) {
std::string actualReplace = *replaceIter;
if (actualReplace.find("${LANG}") != std::string::npos) {
cmSystemTools::ReplaceString(actualReplace, "${LANG}", lang);
@@ -205,7 +207,7 @@ void cmLocalGenerator::TraceDependencies()
std::vector<std::string> configs;
this->Makefile->GetConfigurations(configs);
if (configs.empty()) {
- configs.push_back("");
+ configs.emplace_back();
}
for (std::string const& c : configs) {
this->GlobalGenerator->CreateEvaluationSourceFiles(c);
@@ -484,6 +486,20 @@ void cmLocalGenerator::GenerateInstallRules()
/* clang-format on */
}
+ // Write default directory permissions.
+ if (const char* defaultDirPermissions = this->Makefile->GetDefinition(
+ "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) {
+ /* clang-format off */
+ fout <<
+ "# Set default install directory permissions.\n"
+ "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n"
+ " set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \""
+ << defaultDirPermissions << "\")\n"
+ "endif()\n"
+ "\n";
+ /* clang-format on */
+ }
+
// Ask each install generator to write its code.
std::vector<cmInstallGenerator*> const& installers =
this->Makefile->GetInstallGenerators();
@@ -534,14 +550,13 @@ void cmLocalGenerator::GenerateInstallRules()
void cmLocalGenerator::AddGeneratorTarget(cmGeneratorTarget* gt)
{
this->GeneratorTargets.push_back(gt);
- this->GeneratorTargetSearchIndex.insert(
- std::pair<std::string, cmGeneratorTarget*>(gt->GetName(), gt));
+ this->GeneratorTargetSearchIndex.emplace(gt->GetName(), gt);
this->GlobalGenerator->IndexGeneratorTarget(gt);
}
void cmLocalGenerator::AddImportedGeneratorTarget(cmGeneratorTarget* gt)
{
- this->ImportedGeneratorTargets.push_back(gt);
+ this->ImportedGeneratorTargets.emplace(gt->GetName(), gt);
this->GlobalGenerator->IndexGeneratorTarget(gt);
}
@@ -550,22 +565,6 @@ void cmLocalGenerator::AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt)
this->OwnedImportedGeneratorTargets.push_back(gt);
}
-struct NamedGeneratorTargetFinder
-{
- NamedGeneratorTargetFinder(std::string const& name)
- : Name(name)
- {
- }
-
- bool operator()(cmGeneratorTarget* tgt)
- {
- return tgt->GetName() == this->Name;
- }
-
-private:
- std::string Name;
-};
-
cmGeneratorTarget* cmLocalGenerator::FindLocalNonAliasGeneratorTarget(
const std::string& name) const
{
@@ -583,7 +582,7 @@ void cmLocalGenerator::ComputeTargetManifest()
std::vector<std::string> configNames;
this->Makefile->GetConfigurations(configNames);
if (configNames.empty()) {
- configNames.push_back("");
+ configNames.emplace_back();
}
// Add our targets to the manifest for each configuration.
@@ -604,7 +603,7 @@ bool cmLocalGenerator::ComputeTargetCompileFeatures()
std::vector<std::string> configNames;
this->Makefile->GetConfigurations(configNames);
if (configNames.empty()) {
- configNames.push_back("");
+ configNames.emplace_back();
}
// Process compile features of all targets.
@@ -716,7 +715,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
if (emitted.insert(frameworkDir).second) {
if (sysFwSearchFlag && target &&
- target->IsSystemIncludeDirectory(i, config)) {
+ target->IsSystemIncludeDirectory(i, config, lang)) {
includeFlags << sysFwSearchFlag;
} else {
includeFlags << fwSearchFlag;
@@ -729,7 +728,7 @@ std::string cmLocalGenerator::GetIncludeFlags(
if (!flagUsed || repeatFlag) {
if (sysIncludeFlag && target &&
- target->IsSystemIncludeDirectory(i, config)) {
+ target->IsSystemIncludeDirectory(i, config, lang)) {
includeFlags << sysIncludeFlag;
} else {
includeFlags << includeFlag;
@@ -775,19 +774,14 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
if (const char* langFlagRegexStr =
this->Makefile->GetDefinition(langFlagRegexVar)) {
// Filter flags acceptable to this language.
- cmsys::RegularExpression r(langFlagRegexStr);
std::vector<std::string> opts;
if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
}
target->GetCompileOptions(opts, config, lang);
- for (std::string const& opt : opts) {
- if (r.find(opt.c_str())) {
- // (Re-)Escape this flag. COMPILE_FLAGS were already parsed
- // as a command line above, and COMPILE_OPTIONS are escaped.
- this->AppendFlagEscape(flags, opt);
- }
- }
+ // (Re-)Escape these flags. COMPILE_FLAGS were already parsed
+ // as a command line above, and COMPILE_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, opts, langFlagRegexStr);
} else {
// Use all flags.
if (const char* targetFlags = target->GetProperty("COMPILE_FLAGS")) {
@@ -796,10 +790,8 @@ void cmLocalGenerator::AddCompileOptions(std::string& flags,
}
std::vector<std::string> opts;
target->GetCompileOptions(opts, config, lang);
- for (std::string const& opt : opts) {
- // COMPILE_OPTIONS are escaped.
- this->AppendFlagEscape(flags, opt);
- }
+ // COMPILE_OPTIONS are escaped.
+ this->AppendCompileOptions(flags, opts);
}
for (auto const& it : target->GetMaxLanguageStandards()) {
@@ -894,7 +886,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
for (std::string const& i : impDirVec) {
std::string d = rootPath + i;
cmSystemTools::ConvertToUnixSlashes(d);
- emitted.insert(d);
+ emitted.insert(std::move(d));
if (!stripImplicitInclDirs) {
implicitDirs.push_back(i);
}
@@ -909,8 +901,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// Support putting all the in-project include directories first if
// it is requested by the project.
if (this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) {
- const char* topSourceDir = this->GetState()->GetSourceDirectory();
- const char* topBinaryDir = this->GetState()->GetBinaryDirectory();
+ std::string const &topSourceDir = this->GetState()->GetSourceDirectory(),
+ &topBinaryDir = this->GetState()->GetBinaryDirectory();
for (std::string const& i : includes) {
// Emit this directory only if it is a subdirectory of the
// top-level source or binary tree.
@@ -1383,11 +1375,10 @@ void cmLocalGenerator::AddLanguageFlagsForLinking(
cmGeneratorTarget* cmLocalGenerator::FindGeneratorTargetToUse(
const std::string& name) const
{
- std::vector<cmGeneratorTarget*>::const_iterator imported = std::find_if(
- this->ImportedGeneratorTargets.begin(),
- this->ImportedGeneratorTargets.end(), NamedGeneratorTargetFinder(name));
+ GeneratorTargetMap::const_iterator imported =
+ this->ImportedGeneratorTargets.find(name);
if (imported != this->ImportedGeneratorTargets.end()) {
- return *imported;
+ return imported->second;
}
if (cmGeneratorTarget* t = this->FindLocalNonAliasGeneratorTarget(name)) {
@@ -1422,7 +1413,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
if (cmGeneratorTarget* target = this->FindGeneratorTargetToUse(name)) {
// make sure it is not just a coincidence that the target name
// found is part of the inName
- if (cmSystemTools::FileIsFullPath(inName.c_str())) {
+ if (cmSystemTools::FileIsFullPath(inName)) {
std::string tLocation;
if (target->GetType() >= cmStateEnums::EXECUTABLE &&
target->GetType() <= cmStateEnums::MODULE_LIBRARY) {
@@ -1466,7 +1457,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
}
// The name was not that of a CMake target. It must name a file.
- if (cmSystemTools::FileIsFullPath(inName.c_str())) {
+ if (cmSystemTools::FileIsFullPath(inName)) {
// This is a full path. Return it as given.
dep = inName;
return true;
@@ -1859,7 +1850,7 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
}
void cmLocalGenerator::AppendFlags(std::string& flags,
- const std::string& newFlags)
+ const std::string& newFlags) const
{
if (!newFlags.empty()) {
if (!flags.empty()) {
@@ -1869,7 +1860,8 @@ void cmLocalGenerator::AppendFlags(std::string& flags,
}
}
-void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
+void cmLocalGenerator::AppendFlags(std::string& flags,
+ const char* newFlags) const
{
if (newFlags && *newFlags) {
this->AppendFlags(flags, std::string(newFlags));
@@ -1877,7 +1869,7 @@ void cmLocalGenerator::AppendFlags(std::string& flags, const char* newFlags)
}
void cmLocalGenerator::AppendFlagEscape(std::string& flags,
- const std::string& rawFlag)
+ const std::string& rawFlag) const
{
this->AppendFlags(flags, this->EscapeForShell(rawFlag));
}
@@ -1913,6 +1905,87 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
}
}
+void cmLocalGenerator::AppendCompileOptions(std::string& options,
+ const char* options_list,
+ const char* regex) const
+{
+ // Short-circuit if there are no options.
+ if (!options_list) {
+ return;
+ }
+
+ // Expand the list of options.
+ std::vector<std::string> options_vec;
+ cmSystemTools::ExpandListArgument(options_list, options_vec);
+ this->AppendCompileOptions(options, options_vec, regex);
+}
+
+void cmLocalGenerator::AppendCompileOptions(
+ std::string& options, const std::vector<std::string>& options_vec,
+ const char* regex) const
+{
+ if (regex != nullptr) {
+ // Filter flags upon specified reges.
+ cmsys::RegularExpression r(regex);
+
+ for (std::string const& opt : options_vec) {
+ if (r.find(opt.c_str())) {
+ this->AppendFlagEscape(options, opt);
+ }
+ }
+ } else {
+ for (std::string const& opt : options_vec) {
+ this->AppendFlagEscape(options, opt);
+ }
+ }
+}
+
+void cmLocalGenerator::AppendIncludeDirectories(
+ std::vector<std::string>& includes, const char* includes_list,
+ const cmSourceFile& sourceFile) const
+{
+ // Short-circuit if there are no includes.
+ if (!includes_list) {
+ return;
+ }
+
+ // Expand the list of includes.
+ std::vector<std::string> includes_vec;
+ cmSystemTools::ExpandListArgument(includes_list, includes_vec);
+ this->AppendIncludeDirectories(includes, includes_vec, sourceFile);
+}
+
+void cmLocalGenerator::AppendIncludeDirectories(
+ std::vector<std::string>& includes,
+ const std::vector<std::string>& includes_vec,
+ const cmSourceFile& sourceFile) const
+{
+ std::unordered_set<std::string> uniqueIncludes;
+
+ for (const std::string& include : includes_vec) {
+ if (!cmSystemTools::FileIsFullPath(include)) {
+ std::ostringstream e;
+ e << "Found relative path while evaluating include directories of "
+ "\""
+ << sourceFile.GetLocation().GetName() << "\":\n \"" << include
+ << "\"\n";
+
+ this->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+
+ std::string inc = include;
+
+ if (!cmSystemTools::IsOff(inc.c_str())) {
+ cmSystemTools::ConvertToUnixSlashes(inc);
+ }
+
+ if (uniqueIncludes.insert(inc).second) {
+ includes.push_back(std::move(inc));
+ }
+ }
+}
+
void cmLocalGenerator::AppendDefines(std::set<std::string>& defines,
const char* defines_list) const
{
@@ -2313,14 +2386,14 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
std::string relFromSource =
this->ConvertToRelativePath(this->GetCurrentSourceDirectory(), fullPath);
assert(!relFromSource.empty());
- bool relSource = !cmSystemTools::FileIsFullPath(relFromSource.c_str());
+ bool relSource = !cmSystemTools::FileIsFullPath(relFromSource);
bool subSource = relSource && relFromSource[0] != '.';
// Try referencing the source relative to the binary tree.
std::string relFromBinary =
this->ConvertToRelativePath(this->GetCurrentBinaryDirectory(), fullPath);
assert(!relFromBinary.empty());
- bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary.c_str());
+ bool relBinary = !cmSystemTools::FileIsFullPath(relFromBinary);
bool subBinary = relBinary && relFromBinary[0] != '.';
// Select a nice-looking reference to the source file to construct
@@ -2339,7 +2412,7 @@ std::string cmLocalGenerator::GetObjectFileNameWithoutTarget(
// if it is still a full path check for the try compile case
// try compile never have in source sources, and should not
// have conflicting source file names in the same target
- if (cmSystemTools::FileIsFullPath(objectName.c_str())) {
+ if (cmSystemTools::FileIsFullPath(objectName)) {
if (this->GetGlobalGenerator()->GetCMakeInstance()->GetIsInTryCompile()) {
objectName = cmSystemTools::GetFilenameName(source.GetFullPath());
}
@@ -2397,12 +2470,12 @@ cmake* cmLocalGenerator::GetCMakeInstance() const
return this->GlobalGenerator->GetCMakeInstance();
}
-const char* cmLocalGenerator::GetSourceDirectory() const
+std::string const& cmLocalGenerator::GetSourceDirectory() const
{
return this->GetCMakeInstance()->GetHomeDirectory();
}
-const char* cmLocalGenerator::GetBinaryDirectory() const
+std::string const& cmLocalGenerator::GetBinaryDirectory() const
{
return this->GetCMakeInstance()->GetHomeOutputDirectory();
}
@@ -2541,13 +2614,13 @@ void cmLocalGenerator::GenerateAppleInfoPList(cmGeneratorTarget* target,
// Find the Info.plist template.
const char* in = target->GetProperty("MACOSX_BUNDLE_INFO_PLIST");
std::string inFile = (in && *in) ? in : "MacOSXBundleInfo.plist.in";
- if (!cmSystemTools::FileIsFullPath(inFile.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
if (!inMod.empty()) {
inFile = inMod;
}
}
- if (!cmSystemTools::FileExists(inFile.c_str(), true)) {
+ if (!cmSystemTools::FileExists(inFile, true)) {
std::ostringstream e;
e << "Target " << target->GetName() << " Info.plist template \"" << inFile
<< "\" could not be found.";
@@ -2579,13 +2652,13 @@ void cmLocalGenerator::GenerateFrameworkInfoPList(
// Find the Info.plist template.
const char* in = target->GetProperty("MACOSX_FRAMEWORK_INFO_PLIST");
std::string inFile = (in && *in) ? in : "MacOSXFrameworkInfo.plist.in";
- if (!cmSystemTools::FileIsFullPath(inFile.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(inFile)) {
std::string inMod = this->Makefile->GetModulesFile(inFile.c_str());
if (!inMod.empty()) {
inFile = inMod;
}
}
- if (!cmSystemTools::FileExists(inFile.c_str(), true)) {
+ if (!cmSystemTools::FileExists(inFile, true)) {
std::ostringstream e;
e << "Target " << target->GetName() << " Info.plist template \"" << inFile
<< "\" could not be found.";
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 4a7d2ca64..533ac56ba 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -118,10 +118,11 @@ public:
cmGeneratorTarget const* target,
const std::string& lang);
///! Append flags to a string.
- virtual void AppendFlags(std::string& flags, const std::string& newFlags);
- virtual void AppendFlags(std::string& flags, const char* newFlags);
+ virtual void AppendFlags(std::string& flags,
+ const std::string& newFlags) const;
+ virtual void AppendFlags(std::string& flags, const char* newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
- const std::string& rawFlag);
+ const std::string& rawFlag) const;
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
@@ -138,11 +139,6 @@ public:
return this->GeneratorTargets;
}
- const std::vector<cmGeneratorTarget*>& GetImportedGeneratorTargets() const
- {
- return this->ImportedGeneratorTargets;
- }
-
void AddGeneratorTarget(cmGeneratorTarget* gt);
void AddImportedGeneratorTarget(cmGeneratorTarget* gt);
void AddOwnedImportedGeneratorTarget(cmGeneratorTarget* gt);
@@ -152,6 +148,23 @@ public:
cmGeneratorTarget* FindGeneratorTargetToUse(const std::string& name) const;
/**
+ * Process a list of include directories
+ */
+ void AppendIncludeDirectories(std::vector<std::string>& includes,
+ const char* includes_list,
+ const cmSourceFile& sourceFile) const;
+ void AppendIncludeDirectories(std::vector<std::string>& includes,
+ std::string const& includes_list,
+ const cmSourceFile& sourceFile) const
+ {
+ this->AppendIncludeDirectories(includes, includes_list.c_str(),
+ sourceFile);
+ }
+ void AppendIncludeDirectories(std::vector<std::string>& includes,
+ const std::vector<std::string>& includes_vec,
+ const cmSourceFile& sourceFile) const;
+
+ /**
* Encode a list of preprocessor definitions for the compiler
* command line.
*/
@@ -166,6 +179,22 @@ public:
const std::vector<std::string>& defines_vec) const;
/**
+ * Encode a list of compile options for the compiler
+ * command line.
+ */
+ void AppendCompileOptions(std::string& options, const char* options_list,
+ const char* regex = nullptr) const;
+ void AppendCompileOptions(std::string& options,
+ std::string const& options_list,
+ const char* regex = nullptr) const
+ {
+ this->AppendCompileOptions(options, options_list.c_str(), regex);
+ }
+ void AppendCompileOptions(std::string& options,
+ const std::vector<std::string>& options_vec,
+ const char* regex = nullptr) const;
+
+ /**
* Join a set of defines into a definesString with a space separator.
*/
void JoinDefines(const std::set<std::string>& defines,
@@ -258,8 +287,8 @@ public:
cmake* GetCMakeInstance() const;
- const char* GetSourceDirectory() const;
- const char* GetBinaryDirectory() const;
+ std::string const& GetSourceDirectory() const;
+ std::string const& GetBinaryDirectory() const;
const char* GetCurrentBinaryDirectory() const;
const char* GetCurrentSourceDirectory() const;
@@ -360,7 +389,7 @@ protected:
std::vector<cmGeneratorTarget*> GeneratorTargets;
std::set<cmGeneratorTarget const*> WarnCMP0063;
- std::vector<cmGeneratorTarget*> ImportedGeneratorTargets;
+ GeneratorTargetMap ImportedGeneratorTargets;
std::vector<cmGeneratorTarget*> OwnedImportedGeneratorTargets;
std::map<std::string, std::string> AliasTargets;
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 477ce51f0..8c889fc03 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -207,6 +207,9 @@ void cmLocalNinjaGenerator::WritePools(std::ostream& os)
const char* jobpools =
this->GetCMakeInstance()->GetState()->GetGlobalProperty("JOB_POOLS");
+ if (!jobpools) {
+ jobpools = this->GetMakefile()->GetDefinition("CMAKE_JOB_POOLS");
+ }
if (jobpools) {
cmGlobalNinjaGenerator::WriteComment(
os, "Pools defined by global property JOB_POOLS");
@@ -243,20 +246,6 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusion(std::ostream& os)
os << "\n";
}
-void cmLocalNinjaGenerator::ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt)
-{
- // Determine if these object files should use a custom extension
- char const* custom_ext = gt->GetCustomObjectExtension();
- for (auto& si : mapping) {
- cmSourceFile const* sf = si.first;
- bool keptSourceExtension;
- si.second = this->GetObjectFileNameWithoutTarget(
- *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
- }
-}
-
void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index bb16899be..95d8a61b8 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -23,7 +23,6 @@ class cmGlobalGenerator;
class cmGlobalNinjaGenerator;
class cmMakefile;
class cmRulePlaceholderExpander;
-class cmSourceFile;
class cmake;
/**
@@ -74,10 +73,6 @@ public:
void AppendCustomCommandDeps(cmCustomCommandGenerator const& ccg,
cmNinjaDeps& ninjaDeps);
- void ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = nullptr) override;
-
protected:
std::string ConvertToIncludeReference(
std::string const& path,
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index e26182a15..ddd8cc4c3 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -150,20 +150,6 @@ void cmLocalUnixMakefileGenerator3::ComputeHomeRelativeOutputPath()
}
}
-void cmLocalUnixMakefileGenerator3::ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt)
-{
- // Determine if these object files should use a custom extension
- char const* custom_ext = gt->GetCustomObjectExtension();
- for (auto& si : mapping) {
- cmSourceFile const* sf = si.first;
- bool keptSourceExtension;
- si.second = this->GetObjectFileNameWithoutTarget(
- *sf, gt->ObjectDirectory, &keptSourceExtension, custom_ext);
- }
-}
-
void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
std::map<std::string, LocalObjectInfo>& localObjectFiles)
{
@@ -186,12 +172,12 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
bool hasSourceExtension = true;
std::string objectName =
this->GetObjectFileNameWithoutTarget(*sf, dir, &hasSourceExtension);
- if (cmSystemTools::FileIsFullPath(objectName.c_str())) {
+ if (cmSystemTools::FileIsFullPath(objectName)) {
objectName = cmSystemTools::GetFilenameName(objectName);
}
LocalObjectInfo& info = localObjectFiles[objectName];
info.HasSourceExtension = hasSourceExtension;
- info.push_back(LocalObjectEntry(gt, sf->GetLanguage()));
+ info.emplace_back(gt, sf->GetLanguage());
}
}
}
@@ -539,8 +525,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
// Construct the left hand side of the rule.
std::string tgt = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target)
- .c_str());
+ this->MaybeConvertToRelativePath(this->GetBinaryDirectory(), target));
const char* space = "";
if (tgt.size() == 1) {
@@ -568,7 +553,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
for (std::string const& depend : depends) {
replace = depend;
replace = cmSystemTools::ConvertToOutputPath(
- this->MaybeConvertToRelativePath(binDir, replace).c_str());
+ this->MaybeConvertToRelativePath(binDir, replace));
os << cmMakeSafe(tgt) << space << ": " << cmMakeSafe(replace) << "\n";
}
}
@@ -588,7 +573,7 @@ void cmLocalUnixMakefileGenerator3::WriteMakeRule(
std::string cmLocalUnixMakefileGenerator3::MaybeConvertWatcomShellCommand(
std::string const& cmd)
{
- if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd.c_str()) &&
+ if (this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd) &&
cmd.find_first_of("( )") != std::string::npos) {
// On Watcom WMake use the windows short path for the command
// name. This is needed to avoid funny quoting problems on
@@ -750,11 +735,11 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsTop(
static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
std::string hack = gg->GetEmptyRuleHackDepends();
if (!hack.empty()) {
- no_depends.push_back(hack);
+ no_depends.push_back(std::move(hack));
}
std::string hack_cmd = gg->GetEmptyRuleHackCommand();
if (!hack_cmd.empty()) {
- no_commands.push_back(hack_cmd);
+ no_commands.push_back(std::move(hack_cmd));
}
// Special symbolic target that never exists to force dependers to
@@ -788,7 +773,7 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
std::vector<std::string> no_depends;
std::vector<std::string> commands;
- commands.push_back(runRule);
+ commands.push_back(std::move(runRule));
if (!this->IsRootMakefile()) {
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
@@ -830,8 +815,8 @@ std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
return dir;
}
-void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
- const std::string& newFlags)
+void cmLocalUnixMakefileGenerator3::AppendFlags(
+ std::string& flags, const std::string& newFlags) const
{
if (this->IsWatcomWMake() && !newFlags.empty()) {
std::string newf = newFlags;
@@ -845,7 +830,7 @@ void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
}
void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags,
- const char* newFlags)
+ const char* newFlags) const
{
this->cmLocalGenerator::AppendFlags(flags, newFlags);
}
@@ -888,7 +873,7 @@ void cmLocalUnixMakefileGenerator3::AppendCustomDepend(
// Lookup the real name of the dependency in case it is a CMake target.
std::string dep;
if (this->GetRealDependency(d, this->ConfigName, dep)) {
- depends.push_back(dep);
+ depends.push_back(std::move(dep));
}
}
}
@@ -1037,12 +1022,12 @@ void cmLocalUnixMakefileGenerator3::AppendCustomCommand(
cmd = "echo >nul && " + cmd;
}
}
- commands1.push_back(cmd);
+ commands1.push_back(std::move(cmd));
}
}
// Setup the proper working directory for the commands.
- this->CreateCDCommand(commands1, dir.c_str(), relative);
+ this->CreateCDCommand(commands1, dir, relative);
// push back the custom commands
commands.insert(commands.end(), commands1.begin(), commands1.end());
@@ -1075,12 +1060,14 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
}
fout << ")\n";
}
- std::string remove = "$(CMAKE_COMMAND) -P ";
- remove += this->ConvertToOutputFormat(
- this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(),
- cleanfile),
- cmOutputConverter::SHELL);
- commands.push_back(remove);
+ {
+ std::string remove = "$(CMAKE_COMMAND) -P ";
+ remove += this->ConvertToOutputFormat(
+ this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(),
+ cleanfile),
+ cmOutputConverter::SHELL);
+ commands.push_back(std::move(remove));
+ }
// For the main clean rule add per-language cleaning.
if (!filename) {
@@ -1158,10 +1145,10 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
}
cmd += this->EscapeForShell(line);
}
- commands.push_back(cmd);
+ commands.push_back(std::move(cmd));
}
- // Reset the line to emtpy.
+ // Reset the line to empty.
line.clear();
// Progress appears only on first line.
@@ -1444,6 +1431,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
}
#ifdef CMAKE_BUILD_WITH_CMAKE
else if (lang == "Fortran") {
+ ruleFileStream << "# Note that incremental build could trigger "
+ << "a call to cmake_copy_f90_mod on each re-build\n";
scanner = new cmDependsFortran(this);
} else if (lang == "Java") {
scanner = new cmDependsJava();
@@ -1486,8 +1475,8 @@ void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
// If the depender is missing then delete the dependee to make
// sure both will be regenerated.
- if (cmSystemTools::FileExists(dependee.c_str()) &&
- !cmSystemTools::FileExists(depender.c_str())) {
+ if (cmSystemTools::FileExists(dependee) &&
+ !cmSystemTools::FileExists(depender)) {
if (verbose) {
std::ostringstream msg;
msg << "Deleting primary custom command output \"" << dependee
@@ -1673,13 +1662,15 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
commands.clear();
std::string cmakefileName = cmake::GetCMakeFilesDirectoryPostSlash();
cmakefileName += "Makefile.cmake";
- std::string runRule =
- "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
- runRule += " --check-build-system ";
- runRule +=
- this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
- runRule += " 1";
- commands.push_back(runRule);
+ {
+ std::string runRule =
+ "$(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
+ runRule += " --check-build-system ";
+ runRule +=
+ this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
+ runRule += " 1";
+ commands.push_back(std::move(runRule));
+ }
this->CreateCDCommand(commands, this->GetBinaryDirectory(),
this->GetCurrentBinaryDirectory());
this->WriteMakeRule(ruleFileStream, "clear depends", "depend", depends,
@@ -1836,7 +1827,7 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
this->GetIncludeDirectories(includes, target, implicitLang.first, config);
std::string binaryDir = this->GetState()->GetBinaryDirectory();
if (this->Makefile->IsOn("CMAKE_DEPENDS_IN_PROJECT_ONLY")) {
- const char* sourceDir = this->GetState()->GetSourceDirectory();
+ std::string const& sourceDir = this->GetState()->GetSourceDirectory();
cmEraseIf(includes, ::NotInProjectDir(sourceDir, binaryDir));
}
for (std::string const& include : includes) {
@@ -2037,7 +2028,7 @@ void cmLocalUnixMakefileGenerator3::AddImplicitDepends(
}
void cmLocalUnixMakefileGenerator3::CreateCDCommand(
- std::vector<std::string>& commands, const char* tgtDir,
+ std::vector<std::string>& commands, std::string const& tgtDir,
std::string const& relDir)
{
// do we need to cd?
@@ -2064,7 +2055,7 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand(
// Change back to the starting directory.
cmd = cd_cmd;
cmd += this->ConvertToOutputForExisting(relDir);
- commands.push_back(cmd);
+ commands.push_back(std::move(cmd));
} else {
// On UNIX we must construct a single shell command to change
// directory and build because make resets the directory between
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index b149524b6..bc72f1b30 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -19,7 +19,6 @@ class cmCustomCommandGenerator;
class cmGeneratorTarget;
class cmGlobalGenerator;
class cmMakefile;
-class cmSourceFile;
/** \class cmLocalUnixMakefileGenerator3
* \brief Write a LocalUnix makefiles.
@@ -88,8 +87,9 @@ public:
const std::string& tgt);
// append flags to a string
- void AppendFlags(std::string& flags, const std::string& newFlags) override;
- void AppendFlags(std::string& flags, const char* newFlags) override;
+ void AppendFlags(std::string& flags,
+ const std::string& newFlags) const override;
+ void AppendFlags(std::string& flags, const char* newFlags) const override;
// append an echo command
enum EchoColor
@@ -117,7 +117,8 @@ public:
// create a command that cds to the start dir then runs the commands
void CreateCDCommand(std::vector<std::string>& commands,
- const char* targetDir, std::string const& relDir);
+ std::string const& targetDir,
+ std::string const& relDir);
static std::string ConvertToQuotedOutputPath(const char* p,
bool useWatcomQuote);
@@ -251,10 +252,6 @@ protected:
private:
std::string MaybeConvertWatcomShellCommand(std::string const& cmd);
- void ComputeObjectFilenames(
- std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* gt = nullptr) override;
-
friend class cmMakefileTargetGenerator;
friend class cmMakefileExecutableTargetGenerator;
friend class cmMakefileLibraryTargetGenerator;
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index 5e81514d4..2803d4a50 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -64,20 +64,18 @@ cmLocalVisualStudio10Generator::~cmLocalVisualStudio10Generator()
void cmLocalVisualStudio10Generator::Generate()
{
-
const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmGeneratorTarget* l : tgts) {
+ if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
if (static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator)
- ->TargetIsFortranOnly(*l)) {
- this->CreateSingleVCProj((*l)->GetName().c_str(), *l);
+ ->TargetIsFortranOnly(l)) {
+ this->CreateSingleVCProj(l->GetName(), l);
} else {
cmVisualStudio10TargetGenerator tg(
- *l, static_cast<cmGlobalVisualStudio10Generator*>(
- this->GetGlobalGenerator()));
+ l, static_cast<cmGlobalVisualStudio10Generator*>(
+ this->GetGlobalGenerator()));
tg.Generate();
}
}
diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h
index 4cd56dde3..bcdc30709 100644
--- a/Source/cmLocalVisualStudio10Generator.h
+++ b/Source/cmLocalVisualStudio10Generator.h
@@ -29,13 +29,13 @@ public:
/**
* Generate the makefile for this directory.
*/
- virtual void Generate();
- virtual void ReadAndStoreExternalGUID(const std::string& name,
- const char* path);
+ void Generate() override;
+ void ReadAndStoreExternalGUID(const std::string& name,
+ const char* path) override;
protected:
- virtual const char* ReportErrorLabel() const;
- virtual bool CustomCommandUseLocal() const { return true; }
+ const char* ReportErrorLabel() const override;
+ bool CustomCommandUseLocal() const override { return true; }
private:
};
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index d8030b7fb..98b1c4458 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -36,16 +36,14 @@ private:
cmLocalVisualStudio7Generator* LocalGenerator;
};
-extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
-
-static void cmConvertToWindowsSlash(std::string& s)
+class cmLocalVisualStudio7Generator::AllConfigSources
{
- std::string::size_type pos = 0;
- while ((pos = s.find('/', pos)) != std::string::npos) {
- s[pos] = '\\';
- pos++;
- }
-}
+public:
+ std::vector<cmGeneratorTarget::AllConfigSource> Sources;
+ std::map<cmSourceFile const*, size_t> Index;
+};
+
+extern cmVS7FlagTable cmLocalVisualStudio7GeneratorFlagTable[];
cmLocalVisualStudio7Generator::cmLocalVisualStudio7Generator(
cmGlobalGenerator* gg, cmMakefile* mf)
@@ -63,14 +61,13 @@ void cmLocalVisualStudio7Generator::AddHelperCommands()
{
// Now create GUIDs for targets
const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmGeneratorTarget const* l : tgts) {
+ if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
- const char* path = (*l)->GetProperty("EXTERNAL_MSPROJECT");
+ const char* path = l->GetProperty("EXTERNAL_MSPROJECT");
if (path) {
- this->ReadAndStoreExternalGUID((*l)->GetName().c_str(), path);
+ this->ReadAndStoreExternalGUID(l->GetName(), path);
}
}
@@ -83,38 +80,14 @@ void cmLocalVisualStudio7Generator::Generate()
this->WriteStampFiles();
}
-void cmLocalVisualStudio7Generator::AddCMakeListsRules()
-{
- // Create the regeneration custom rule.
- if (!this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
- // Create a rule to regenerate the build system when the target
- // specification source changes.
- if (cmSourceFile* sf = this->CreateVCProjBuildRule()) {
- // Add the rule to targets that need it.
- const std::vector<cmGeneratorTarget*>& tgts =
- this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
- l != tgts.end(); ++l) {
- if ((*l)->GetType() == cmStateEnums::GLOBAL_TARGET) {
- continue;
- }
- if ((*l)->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
- (*l)->AddSource(sf->GetFullPath());
- }
- }
- }
- }
-}
-
void cmLocalVisualStudio7Generator::FixGlobalTargets()
{
// Visual Studio .NET 2003 Service Pack 1 will not run post-build
// commands for targets in which no sources are built. Add dummy
// rules to force these targets to build.
const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
- for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
- l != tgts.end(); l++) {
- if ((*l)->GetType() == cmStateEnums::GLOBAL_TARGET) {
+ for (cmGeneratorTarget* l : tgts) {
+ if (l->GetType() == cmStateEnums::GLOBAL_TARGET) {
std::vector<std::string> no_depends;
cmCustomCommandLine force_command;
force_command.push_back("cd");
@@ -125,12 +98,12 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
std::string force = this->GetCurrentBinaryDirectory();
force += cmake::GetCMakeFilesDirectory();
force += "/";
- force += (*l)->GetName();
+ force += l->GetName();
force += "_force";
if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput(
force.c_str(), no_depends, no_main_dependency, force_commands, " ",
0, true)) {
- (*l)->AddSource(file->GetFullPath());
+ l->AddSource(file->GetFullPath());
}
}
}
@@ -142,8 +115,7 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
void cmLocalVisualStudio7Generator::WriteProjectFiles()
{
// If not an in source build, then create the output directory
- if (strcmp(this->GetCurrentBinaryDirectory(), this->GetSourceDirectory()) !=
- 0) {
+ if (this->GetCurrentBinaryDirectory() != this->GetSourceDirectory()) {
if (!cmSystemTools::MakeDirectory(this->GetCurrentBinaryDirectory())) {
cmSystemTools::Error("Error creating directory ",
this->GetCurrentBinaryDirectory());
@@ -154,15 +126,14 @@ void cmLocalVisualStudio7Generator::WriteProjectFiles()
const std::vector<cmGeneratorTarget*>& tgts = this->GetGeneratorTargets();
// Create the project file for each target.
- for (std::vector<cmGeneratorTarget*>::const_iterator l = tgts.begin();
- l != tgts.end(); l++) {
- if ((*l)->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ for (cmGeneratorTarget* l : tgts) {
+ if (l->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
// INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
// so don't build a projectfile for it
- if (!(*l)->GetProperty("EXTERNAL_MSPROJECT")) {
- this->CreateSingleVCProj((*l)->GetName().c_str(), *l);
+ if (!l->GetProperty("EXTERNAL_MSPROJECT")) {
+ this->CreateSingleVCProj(l->GetName(), l);
}
}
}
@@ -239,19 +210,29 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
{
+ if (this->Makefile->IsOn("CMAKE_SUPPRESS_REGENERATION")) {
+ return nullptr;
+ }
+
+ std::string makefileIn = this->GetCurrentSourceDirectory();
+ makefileIn += "/";
+ makefileIn += "CMakeLists.txt";
+ makefileIn = cmSystemTools::CollapseFullPath(makefileIn);
+ if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
+ if (file->GetCustomCommand()) {
+ return file;
+ }
+ }
+ if (!cmSystemTools::FileExists(makefileIn)) {
+ return nullptr;
+ }
+
std::string stampName = this->GetCurrentBinaryDirectory();
stampName += "/";
stampName += cmake::GetCMakeFilesDirectoryPostSlash();
stampName += "generate.stamp";
cmCustomCommandLine commandLine;
commandLine.push_back(cmSystemTools::GetCMakeCommand());
- std::string makefileIn = this->GetCurrentSourceDirectory();
- makefileIn += "/";
- makefileIn += "CMakeLists.txt";
- makefileIn = cmSystemTools::CollapseFullPath(makefileIn.c_str());
- if (!cmSystemTools::FileExists(makefileIn.c_str())) {
- return 0;
- }
std::string comment = "Building Custom Rule ";
comment += makefileIn;
std::string args;
@@ -275,10 +256,13 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
fullpathStampName.c_str(), listFiles, makefileIn.c_str(), commandLines,
comment.c_str(), no_working_directory, true, false);
if (cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str())) {
+ // Finalize the source file path now since we're adding this after
+ // the generator validated all project-named sources.
+ file->GetFullPath();
return file;
} else {
cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
- return 0;
+ return nullptr;
}
}
@@ -618,6 +602,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
switch (target->GetType()) {
case cmStateEnums::OBJECT_LIBRARY:
targetBuilds = false; // no manifest tool for object library
+ CM_FALLTHROUGH;
case cmStateEnums::STATIC_LIBRARY:
projectType = "typeStaticLibrary";
configType = "4";
@@ -633,6 +618,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
case cmStateEnums::UTILITY:
case cmStateEnums::GLOBAL_TARGET:
configType = "10";
+ CM_FALLTHROUGH;
default:
targetBuilds = false;
break;
@@ -641,7 +627,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
configType = projectType;
}
std::string flags;
- if (strcmp(configType, "10") != 0) {
+ std::string langForClCompile;
+ if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
const std::string& linkLanguage =
(this->FortranProject ? std::string("Fortran")
: target->GetLinkerLanguage(configName));
@@ -651,10 +638,11 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
target->GetName().c_str());
return;
}
- if (linkLanguage == "C" || linkLanguage == "CXX" ||
- linkLanguage == "Fortran") {
+ langForClCompile = linkLanguage;
+ if (langForClCompile == "C" || langForClCompile == "CXX" ||
+ langForClCompile == "Fortran") {
std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
+ baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
flags = this->Makefile->GetRequiredDefinition(baseFlagVar.c_str());
std::string flagVar =
@@ -671,7 +659,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
}
// Add the target-specific flags.
- this->AddCompileOptions(flags, target, linkLanguage, configName);
+ this->AddCompileOptions(flags, target, langForClCompile, configName);
// Check IPO related warning/error.
target->IsIPOEnabled(linkLanguage, configName);
@@ -702,13 +690,20 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
Options targetOptions(this, t, table, gg->ExtraFlagTable);
targetOptions.FixExceptionHandlingDefault();
std::string asmLocation = configName + "/";
- targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+ targetOptions.AddFlag("AssemblerListingLocation", asmLocation);
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
- std::vector<std::string> targetDefines;
- target->GetCompileDefinitions(targetDefines, configName, "CXX");
- targetOptions.AddDefines(targetDefines);
+ if (!langForClCompile.empty()) {
+ std::vector<std::string> targetDefines;
+ target->GetCompileDefinitions(targetDefines, configName, langForClCompile);
+ targetOptions.AddDefines(targetDefines);
+
+ std::vector<std::string> targetIncludes;
+ this->GetIncludeDirectories(targetIncludes, target, langForClCompile,
+ configName);
+ targetOptions.AddIncludes(targetIncludes);
+ }
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -795,26 +790,12 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
<< this->ConvertToXMLOutputPath(modDir.c_str())
<< "\\$(ConfigurationName)\"\n";
}
- fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
- std::vector<std::string> includes;
- this->GetIncludeDirectories(includes, target, "C", configName);
- std::vector<std::string>::iterator i = includes.begin();
- for (; i != includes.end(); ++i) {
- // output the include path
- std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
- fout << ipath << ";";
- // if this is fortran then output the include with
- // a ConfigurationName on the end of it.
- if (this->FortranProject) {
- ipath = i->c_str();
- ipath += "/$(ConfigurationName)";
- ipath = this->ConvertToXMLOutputPath(ipath.c_str());
- fout << ipath << ";";
- }
- }
- fout << "\"\n";
+ targetOptions.OutputAdditionalIncludeDirectories(
+ fout, "\t\t\t\t", "\n",
+ this->FortranProject ? "Fortran" : langForClCompile);
targetOptions.OutputFlagMap(fout, "\t\t\t\t");
- targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n", "CXX");
+ targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
+ langForClCompile);
fout << "\t\t\t\tObjectFile=\"$(IntDir)\\\"\n";
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
// Specify the compiler program database file if configured.
@@ -831,17 +812,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
fout <<
"\t\t\t<Tool\n"
"\t\t\t\tName=\"MASM\"\n"
- "\t\t\t\tIncludePaths=\""
;
/* clang-format on */
- const char* sep = "";
- for (i = includes.begin(); i != includes.end(); ++i) {
- std::string inc = *i;
- cmConvertToWindowsSlash(inc);
- fout << sep << this->EscapeForXML(inc);
- sep = ";";
- }
- fout << "\"\n";
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\t\t\t\t", "\n",
+ "ASM_MASM");
// Use same preprocessor definitions as VCCLCompilerTool.
targetOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t", "\n",
"ASM_MASM");
@@ -861,14 +835,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
if (this->FortranProject) {
tool = "VFResourceCompilerTool";
}
- fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n"
- << "\t\t\t\tAdditionalIncludeDirectories=\"";
- for (i = includes.begin(); i != includes.end(); ++i) {
- std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
- fout << ipath << ";";
- }
+ fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
+ "RC");
// add the -D flags to the RC tool
- fout << "\"";
targetOptions.OutputPreprocessorDefinitions(fout, "\n\t\t\t\t", "", "RC");
fout << "/>\n";
tool = "VCMIDLTool";
@@ -876,12 +846,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
tool = "VFMIDLTool";
}
fout << "\t\t\t<Tool\n\t\t\t\tName=\"" << tool << "\"\n";
- fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
- for (i = includes.begin(); i != includes.end(); ++i) {
- std::string ipath = this->ConvertToXMLOutputPath(i->c_str());
- fout << ipath << ";";
- }
- fout << "\"\n";
+ targetOptions.OutputAdditionalIncludeDirectories(fout, "\n\t\t\t\t", "",
+ "MIDL");
fout << "\t\t\t\tMkTypLibCompatible=\"false\"\n";
if (gg->GetPlatformName() == "x64") {
fout << "\t\t\t\tTargetEnvironment=\"3\"\n";
@@ -1008,7 +974,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
if (mdi && !mdi->DefFile.empty()) {
std::string defFile =
this->ConvertToOutputFormat(mdi->DefFile, cmOutputConverter::SHELL);
- linkOptions.AddFlag("ModuleDefinitionFile", defFile.c_str());
+ linkOptions.AddFlag("ModuleDefinitionFile", defFile);
}
switch (target->GetType()) {
@@ -1368,13 +1334,26 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
// We may be modifying the source groups temporarily, so make a copy.
std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups();
- std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
- target->GetAllConfigSources();
- std::map<cmSourceFile const*, size_t> sourcesIndex;
+ AllConfigSources sources;
+ sources.Sources = target->GetAllConfigSources();
+
+ // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
+ if (target->GetType() != cmStateEnums::GLOBAL_TARGET &&
+ target->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ if (cmSourceFile const* sf = this->CreateVCProjBuildRule()) {
+ cmGeneratorTarget::AllConfigSource acs;
+ acs.Source = sf;
+ acs.Kind = cmGeneratorTarget::SourceKindCustomCommand;
+ for (size_t ci = 0; ci < configs.size(); ++ci) {
+ acs.Configs.push_back(ci);
+ }
+ sources.Sources.emplace_back(std::move(acs));
+ }
+ }
- for (size_t si = 0; si < sources.size(); ++si) {
- cmSourceFile const* sf = sources[si].Source;
- sourcesIndex[sf] = si;
+ for (size_t si = 0; si < sources.Sources.size(); ++si) {
+ cmSourceFile const* sf = sources.Sources[si].Source;
+ sources.Index[sf] = si;
if (!sf->GetObjectLibrary().empty()) {
if (this->FortranProject) {
// Intel Fortran does not support per-config source locations
@@ -1386,7 +1365,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
// Add the file to the list of sources.
std::string const source = sf->GetFullPath();
cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ this->Makefile->FindSourceGroup(source, sourceGroups);
sourceGroup->AssignSource(sf);
}
@@ -1400,7 +1379,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout,
// Loop through every source group.
for (unsigned int i = 0; i < sourceGroups.size(); ++i) {
cmSourceGroup sg = sourceGroups[i];
- this->WriteGroup(&sg, target, fout, libName, configs, sourcesIndex);
+ this->WriteGroup(&sg, target, fout, libName, configs, sources);
}
fout << "\t</Files>\n";
@@ -1416,6 +1395,7 @@ struct cmLVS7GFileConfig
std::string CompileDefs;
std::string CompileDefsConfig;
std::string AdditionalDeps;
+ std::string IncludeDirs;
bool ExcludedFromBuild;
};
@@ -1446,15 +1426,34 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
i != configs.end(); ++i, ++ci) {
std::string configUpper = cmSystemTools::UpperCase(*i);
cmLVS7GFileConfig fc;
+
+ std::string lang =
+ lg->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
+ const std::string& sourceLang = lg->GetSourceFileLanguage(sf);
+ bool needForceLang = false;
+ // source file does not match its extension language
+ if (lang != sourceLang) {
+ needForceLang = true;
+ lang = sourceLang;
+ }
+
+ cmGeneratorExpressionInterpreter genexInterpreter(lg, gt, *i,
+ gt->GetName(), lang);
+
bool needfc = false;
if (!objectName.empty()) {
fc.ObjectName = objectName;
needfc = true;
}
- if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
- fc.CompileFlags = cge->Evaluate(lg, *i, false, gt);
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = sf.GetProperty(COMPILE_FLAGS)) {
+ fc.CompileFlags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
+ needfc = true;
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = sf.GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ fc.CompileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
needfc = true;
}
if (lg->FortranProject) {
@@ -1472,14 +1471,22 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
break;
}
}
- if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
- fc.CompileDefs = cdefs;
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* cdefs = sf.GetProperty(COMPILE_DEFINITIONS)) {
+ fc.CompileDefs = genexInterpreter.Evaluate(cdefs, COMPILE_DEFINITIONS);
needfc = true;
}
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
- if (const char* ccdefs = sf.GetProperty(defPropName.c_str())) {
- fc.CompileDefsConfig = ccdefs;
+ if (const char* ccdefs = sf.GetProperty(defPropName)) {
+ fc.CompileDefsConfig =
+ genexInterpreter.Evaluate(ccdefs, COMPILE_DEFINITIONS);
+ needfc = true;
+ }
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincs = sf.GetProperty(INCLUDE_DIRECTORIES)) {
+ fc.IncludeDirs = genexInterpreter.Evaluate(cincs, INCLUDE_DIRECTORIES);
needfc = true;
}
@@ -1497,16 +1504,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
}
}
- std::string lang =
- lg->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
- const std::string& sourceLang = lg->GetSourceFileLanguage(sf);
const std::string& linkLanguage = gt->GetLinkerLanguage(i->c_str());
- bool needForceLang = false;
- // source file does not match its extension language
- if (lang != sourceLang) {
- needForceLang = true;
- lang = sourceLang;
- }
// If HEADER_FILE_ONLY is set, we must suppress this generation in
// the project file
fc.ExcludedFromBuild = sf.GetPropertyAsBool("HEADER_FILE_ONLY") ||
@@ -1567,7 +1565,7 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
bool cmLocalVisualStudio7Generator::WriteGroup(
const cmSourceGroup* sg, cmGeneratorTarget* target, std::ostream& fout,
const std::string& libName, std::vector<std::string> const& configs,
- std::map<cmSourceFile const*, size_t> const& sourcesIndex)
+ AllConfigSources const& sources)
{
cmGlobalVisualStudio7Generator* gg =
static_cast<cmGlobalVisualStudio7Generator*>(this->GlobalGenerator);
@@ -1579,7 +1577,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
std::ostringstream tmpOut;
for (unsigned int i = 0; i < children.size(); ++i) {
if (this->WriteGroup(&children[i], target, tmpOut, libName, configs,
- sourcesIndex)) {
+ sources)) {
hasChildrenWithSources = true;
}
}
@@ -1590,14 +1588,11 @@ 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(), "");
}
- std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
- target->GetAllConfigSources();
-
// Loop through each source in the source group.
for (std::vector<const cmSourceFile*>::const_iterator sf =
sourceFiles.begin();
@@ -1608,10 +1603,11 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
target->GetType() == cmStateEnums::GLOBAL_TARGET) {
// Look up the source kind and configs.
std::map<cmSourceFile const*, size_t>::const_iterator map_it =
- sourcesIndex.find(*sf);
+ sources.Index.find(*sf);
// The map entry must exist because we populated it earlier.
- assert(map_it != sourcesIndex.end());
- cmGeneratorTarget::AllConfigSource const& acs = sources[map_it->second];
+ assert(map_it != sources.Index.end());
+ cmGeneratorTarget::AllConfigSource const& acs =
+ sources.Sources[map_it->second];
FCInfo fcinfo(this, target, acs, configs);
@@ -1624,7 +1620,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
this->WriteCustomRule(fout, configs, source.c_str(), *command, fcinfo);
} else if (!fcinfo.FileConfigMap.empty()) {
const char* aCompilerTool = "VCCLCompilerTool";
- const char* ppLang = "CXX";
+ std::string ppLang = "CXX";
if (this->FortranProject) {
aCompilerTool = "VFFortranCompilerTool";
}
@@ -1671,7 +1667,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << aCompilerTool << "\"\n";
if (!fc.CompileFlags.empty() || !fc.CompileDefs.empty() ||
- !fc.CompileDefsConfig.empty()) {
+ !fc.CompileDefsConfig.empty() || !fc.IncludeDirs.empty()) {
Options::Tool tool = Options::Compiler;
cmVS7FlagTable const* table =
cmLocalVisualStudio7GeneratorFlagTable;
@@ -1683,7 +1679,14 @@ bool cmLocalVisualStudio7Generator::WriteGroup(
fileOptions.Parse(fc.CompileFlags.c_str());
fileOptions.AddDefines(fc.CompileDefs.c_str());
fileOptions.AddDefines(fc.CompileDefsConfig.c_str());
+ // validate source level include directories
+ std::vector<std::string> includes;
+ this->AppendIncludeDirectories(includes, fc.IncludeDirs, **sf);
+ fileOptions.AddIncludes(includes);
fileOptions.OutputFlagMap(fout, "\t\t\t\t\t");
+ fileOptions.OutputAdditionalIncludeDirectories(
+ fout, "\t\t\t\t\t", "\n",
+ ppLang == "CXX" && this->FortranProject ? "Fortran" : ppLang);
fileOptions.OutputPreprocessorDefinitions(fout, "\t\t\t\t\t", "\n",
ppLang);
}
diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h
index 7a77574fa..02e6931d3 100644
--- a/Source/cmLocalVisualStudio7Generator.h
+++ b/Source/cmLocalVisualStudio7Generator.h
@@ -35,12 +35,12 @@ public:
virtual ~cmLocalVisualStudio7Generator();
- virtual void AddHelperCommands();
+ void AddHelperCommands() override;
/**
* Generate the makefile for this directory.
*/
- virtual void Generate();
+ void Generate() override;
enum BuildType
{
@@ -56,16 +56,15 @@ public:
*/
void SetBuildType(BuildType, const std::string& name);
- virtual std::string GetTargetDirectory(
- cmGeneratorTarget const* target) const;
+ std::string GetTargetDirectory(
+ cmGeneratorTarget const* target) const override;
cmSourceFile* CreateVCProjBuildRule();
void WriteStampFiles();
- virtual std::string ComputeLongestObjectDirectory(
- cmGeneratorTarget const*) const;
+ std::string ComputeLongestObjectDirectory(
+ cmGeneratorTarget const*) const override;
virtual void ReadAndStoreExternalGUID(const std::string& name,
const char* path);
- virtual void AddCMakeListsRules();
protected:
void CreateSingleVCProj(const std::string& lname, cmGeneratorTarget* tgt);
@@ -117,10 +116,11 @@ private:
FCInfo& fcinfo);
void WriteTargetVersionAttribute(std::ostream& fout, cmGeneratorTarget* gt);
+ class AllConfigSources;
bool WriteGroup(const cmSourceGroup* sg, cmGeneratorTarget* target,
std::ostream& fout, const std::string& libName,
std::vector<std::string> const& configs,
- std::map<cmSourceFile const*, size_t> const& sourcesIndex);
+ AllConfigSources const& sources);
friend class cmLocalVisualStudio7GeneratorFCInfo;
friend class cmLocalVisualStudio7GeneratorInternals;
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index bbb91e04b..2237da75f 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -39,10 +39,8 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
// windows file names are not case sensitive.
std::map<std::string, int> counts;
- for (std::map<cmSourceFile const*, std::string>::iterator si =
- mapping.begin();
- si != mapping.end(); ++si) {
- cmSourceFile const* sf = si->first;
+ for (auto const& si : mapping) {
+ cmSourceFile const* sf = si.first;
std::string objectNameLower = cmSystemTools::LowerCase(
cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
if (custom_ext) {
@@ -57,10 +55,8 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
// For all source files producing duplicate names we need unique
// object name computation.
- for (std::map<cmSourceFile const*, std::string>::iterator si =
- mapping.begin();
- si != mapping.end(); ++si) {
- cmSourceFile const* sf = si->first;
+ for (auto& si : mapping) {
+ cmSourceFile const* sf = si.first;
std::string objectName =
cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
if (custom_ext) {
@@ -74,7 +70,7 @@ void cmLocalVisualStudioGenerator::ComputeObjectFilenames(
objectName = this->GetObjectFileNameWithoutTarget(
*sf, dir_max, &keptSourceExtension, custom_ext);
}
- si->second = objectName;
+ si.second = objectName;
}
}
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index cba24fed7..3fdafd2b2 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -44,11 +44,9 @@ public:
virtual std::string ComputeLongestObjectDirectory(
cmGeneratorTarget const*) const = 0;
- virtual void AddCMakeListsRules() = 0;
-
- virtual void ComputeObjectFilenames(
+ void ComputeObjectFilenames(
std::map<cmSourceFile const*, std::string>& mapping,
- cmGeneratorTarget const* = 0);
+ cmGeneratorTarget const* = 0) override;
protected:
virtual const char* ReportErrorLabel() const;
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 853e66c23..92c958d05 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -31,10 +31,10 @@ std::string cmLocalXCodeGenerator::GetTargetDirectory(
}
void cmLocalXCodeGenerator::AppendFlagEscape(std::string& flags,
- const std::string& rawFlag)
+ const std::string& rawFlag) const
{
- cmGlobalXCodeGenerator* gg =
- static_cast<cmGlobalXCodeGenerator*>(this->GlobalGenerator);
+ const cmGlobalXCodeGenerator* gg =
+ static_cast<const cmGlobalXCodeGenerator*>(this->GlobalGenerator);
gg->AppendFlag(flags, rawFlag);
}
@@ -42,8 +42,7 @@ void cmLocalXCodeGenerator::Generate()
{
cmLocalGenerator::Generate();
- const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
- for (auto target : targets) {
+ for (auto target : this->GetGeneratorTargets()) {
target->HasMacOSXRpathInstallNameDir("");
}
}
@@ -52,8 +51,7 @@ void cmLocalXCodeGenerator::GenerateInstallRules()
{
cmLocalGenerator::GenerateInstallRules();
- const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets();
- for (auto target : targets) {
+ for (auto target : this->GetGeneratorTargets()) {
target->HasMacOSXRpathInstallNameDir("");
}
}
diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h
index 8c9596f85..5c22dcf68 100644
--- a/Source/cmLocalXCodeGenerator.h
+++ b/Source/cmLocalXCodeGenerator.h
@@ -31,7 +31,7 @@ public:
std::string GetTargetDirectory(
cmGeneratorTarget const* target) const override;
void AppendFlagEscape(std::string& flags,
- const std::string& rawFlag) override;
+ const std::string& rawFlag) const override;
void Generate() override;
virtual void GenerateInstallRules();
void ComputeObjectFilenames(
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 74a1da00e..07943e344 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -4,6 +4,7 @@
#include <sstream>
#include <stdio.h>
+#include <utility>
#include "cmAlgorithms.h"
#include "cmExecutionStatus.h"
@@ -131,7 +132,7 @@ bool cmMacroHelperCommand::InvokeInitialPass(
}
arg.Delim = k.Delim;
arg.Line = k.Line;
- newLFF.Arguments.push_back(arg);
+ newLFF.Arguments.push_back(std::move(arg));
}
cmExecutionStatus status;
if (!this->Makefile->ExecuteCommand(newLFF, status) ||
diff --git a/Source/cmMakeDirectoryCommand.cxx b/Source/cmMakeDirectoryCommand.cxx
index 06e295bc0..aff4ca650 100644
--- a/Source/cmMakeDirectoryCommand.cxx
+++ b/Source/cmMakeDirectoryCommand.cxx
@@ -15,13 +15,13 @@ bool cmMakeDirectoryCommand::InitialPass(std::vector<std::string> const& args,
this->SetError("called with incorrect number of arguments");
return false;
}
- if (!this->Makefile->CanIWriteThisFile(args[0].c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(args[0])) {
std::string e = "attempted to create a directory: " + args[0] +
" into a source directory.";
this->SetError(e);
cmSystemTools::SetFatalErrorOccured();
return false;
}
- cmSystemTools::MakeDirectory(args[0].c_str());
+ cmSystemTools::MakeDirectory(args[0]);
return true;
}
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 5643c978d..b46820822 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -7,6 +7,7 @@
#include <algorithm>
#include <assert.h>
#include <ctype.h>
+#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdlib.h>
@@ -19,7 +20,7 @@
#include "cmCustomCommand.h"
#include "cmCustomCommandLines.h"
#include "cmExecutionStatus.h"
-#include "cmExpandedCommandArgument.h"
+#include "cmExpandedCommandArgument.h" // IWYU pragma: keep
#include "cmFileLockPool.h"
#include "cmFunctionBlocker.h"
#include "cmGeneratorExpression.h"
@@ -94,8 +95,7 @@ cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator,
this->AddSourceGroup("Object Files", "\\.(lo|o|obj)$");
this->ObjectLibrariesSourceGroupIndex = this->SourceGroups.size();
- this->SourceGroups.push_back(
- cmSourceGroup("Object Libraries", "^MATCH_NO_SOURCES$"));
+ this->SourceGroups.emplace_back("Object Libraries", "^MATCH_NO_SOURCES$");
#endif
}
@@ -122,6 +122,42 @@ void cmMakefile::IssueMessage(cmake::MessageType t,
this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace());
}
+bool cmMakefile::CheckCMP0037(std::string const& targetName,
+ cmStateEnums::TargetType targetType) const
+{
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ std::ostringstream e;
+ bool issueMessage = false;
+ switch (this->GetPolicyStatus(cmPolicies::CMP0037)) {
+ case cmPolicies::WARN:
+ if (targetType != cmStateEnums::INTERFACE_LIBRARY) {
+ e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n";
+ issueMessage = true;
+ }
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ issueMessage = true;
+ messageType = cmake::FATAL_ERROR;
+ break;
+ }
+ if (issueMessage) {
+ e << "The target name \"" << targetName
+ << "\" is reserved or not valid for certain "
+ "CMake features, such as generator expressions, and may result "
+ "in undefined behavior.";
+ this->IssueMessage(messageType, e.str());
+
+ if (messageType == cmake::FATAL_ERROR) {
+ return false;
+ }
+ }
+ return true;
+}
+
cmStringRange cmMakefile::GetIncludeDirectoriesEntries() const
{
return this->StateSnapshot.GetDirectory().GetIncludeDirectoriesEntries();
@@ -562,7 +598,7 @@ void cmMakefile::EnforceDirectoryLevelRules() const
<< "\"cmake --help-policy CMP0000\".";
switch (this->GetPolicyStatus(cmPolicies::CMP0000)) {
case cmPolicies::WARN:
- // Warn because the user did not provide a mimimum required
+ // Warn because the user did not provide a minimum required
// version.
this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING,
msg.str(), this->Backtrace);
@@ -627,7 +663,7 @@ struct file_not_persistent
bool operator()(const std::string& path) const
{
return !(path.find("CMakeTmp") == std::string::npos &&
- cmSystemTools::FileExists(path.c_str()));
+ cmSystemTools::FileExists(path));
}
};
}
@@ -718,8 +754,9 @@ void cmMakefile::AddCustomCommandToTarget(
return;
}
+ cmTarget& t = ti->second;
if (objLibraryCommands == RejectObjectLibraryCommands &&
- ti->second.GetType() == cmStateEnums::OBJECT_LIBRARY) {
+ t.GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Target \"" << target
<< "\" is an OBJECT library "
@@ -727,7 +764,7 @@ void cmMakefile::AddCustomCommandToTarget(
this->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (ti->second.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
+ if (t.GetType() == cmStateEnums::INTERFACE_LIBRARY) {
std::ostringstream e;
e << "Target \"" << target
<< "\" is an INTERFACE library "
@@ -754,13 +791,13 @@ void cmMakefile::AddCustomCommandToTarget(
cc.SetDepfile(depfile);
switch (type) {
case cmTarget::PRE_BUILD:
- ti->second.AddPreBuildCommand(cc);
+ t.AddPreBuildCommand(cc);
break;
case cmTarget::PRE_LINK:
- ti->second.AddPreLinkCommand(cc);
+ t.AddPreLinkCommand(cc);
break;
case cmTarget::POST_BUILD:
- ti->second.AddPostBuildCommand(cc);
+ t.AddPostBuildCommand(cc);
break;
}
}
@@ -818,7 +855,7 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
std::string outName = gg->GenerateRuleFile(outputs[0]);
// Check if the rule file already exists.
- file = this->GetSource(outName);
+ file = this->GetSource(outName, cmSourceFileLocationKind::Known);
if (file && file->GetCustomCommand() && !replace) {
// The rule file already exists.
if (commandLines != file->GetCustomCommand()->GetCommandLines()) {
@@ -831,19 +868,22 @@ cmSourceFile* cmMakefile::AddCustomCommandToOutput(
// Create a cmSourceFile for the rule file.
if (!file) {
- file = this->CreateSource(outName, true);
+ file =
+ this->CreateSource(outName, true, cmSourceFileLocationKind::Known);
}
file->SetProperty("__CMAKE_RULE", "1");
}
// Always create the output sources and mark them generated.
for (std::string const& o : outputs) {
- if (cmSourceFile* out = this->GetOrCreateSource(o, true)) {
+ if (cmSourceFile* out =
+ this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) {
out->SetProperty("GENERATED", "1");
}
}
for (std::string const& o : byproducts) {
- if (cmSourceFile* out = this->GetOrCreateSource(o, true)) {
+ if (cmSourceFile* out =
+ this->GetOrCreateSource(o, true, cmSourceFileLocationKind::Known)) {
out->SetProperty("GENERATED", "1");
}
}
@@ -930,7 +970,7 @@ void cmMakefile::AddCustomCommandOldStyle(
}
// Each output must get its own copy of this rule.
- cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|"
+ cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|m|mm|"
"rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
"hm|hpp|hxx|in|txx|inl)$");
for (std::string const& oi : outputs) {
@@ -970,7 +1010,7 @@ void cmMakefile::AddCustomCommandOldStyle(
}
cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
const std::vector<std::string>& depends, const char* workingDirectory,
const char* command, const char* arg1, const char* arg2, const char* arg3,
const char* arg4)
@@ -991,28 +1031,28 @@ cmTarget* cmMakefile::AddUtilityCommand(
commandLine.push_back(arg4);
}
cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
+ commandLines.push_back(std::move(commandLine));
// Call the real signature of this method.
- return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
- depends, commandLines);
+ return this->AddUtilityCommand(utilityName, origin, excludeFromAll,
+ workingDirectory, depends, commandLines);
}
cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
const char* workingDirectory, const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle,
const char* comment, bool uses_terminal, bool command_expand_lists)
{
std::vector<std::string> no_byproducts;
- return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
- no_byproducts, depends, commandLines,
- escapeOldStyle, comment, uses_terminal,
- command_expand_lists);
+ return this->AddUtilityCommand(utilityName, origin, excludeFromAll,
+ workingDirectory, no_byproducts, depends,
+ commandLines, escapeOldStyle, comment,
+ uses_terminal, command_expand_lists);
}
cmTarget* cmMakefile::AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
const char* workingDirectory, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle,
@@ -1020,6 +1060,7 @@ cmTarget* cmMakefile::AddUtilityCommand(
{
// Create a target instance for this utility.
cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName);
+ target->SetIsGeneratorProvided(origin == TargetOrigin::Generator);
if (excludeFromAll) {
target->SetProperty("EXCLUDE_FROM_ALL", "TRUE");
}
@@ -1054,7 +1095,8 @@ cmTarget* cmMakefile::AddUtilityCommand(
// Always create the byproduct sources and mark them generated.
for (std::string const& byproduct : byproducts) {
- if (cmSourceFile* out = this->GetOrCreateSource(byproduct, true)) {
+ if (cmSourceFile* out = this->GetOrCreateSource(
+ byproduct, true, cmSourceFileLocationKind::Known)) {
out->SetProperty("GENERATED", "1");
}
}
@@ -1062,9 +1104,9 @@ cmTarget* cmMakefile::AddUtilityCommand(
return target;
}
-void cmMakefile::AddDefineFlag(const char* flag)
+void cmMakefile::AddDefineFlag(std::string const& flag)
{
- if (!flag) {
+ if (flag.empty()) {
return;
}
@@ -1080,7 +1122,7 @@ void cmMakefile::AddDefineFlag(const char* flag)
this->AddDefineFlag(flag, this->DefineFlags);
}
-void cmMakefile::AddDefineFlag(const char* flag, std::string& dflags)
+void cmMakefile::AddDefineFlag(std::string const& flag, std::string& dflags)
{
// remove any \n\r
std::string::size_type initSize = dflags.size();
@@ -1090,14 +1132,13 @@ void cmMakefile::AddDefineFlag(const char* flag, std::string& dflags)
std::replace(flagStart, dflags.end(), '\r', ' ');
}
-void cmMakefile::RemoveDefineFlag(const char* flag)
+void cmMakefile::RemoveDefineFlag(std::string const& flag)
{
// Check the length of the flag to remove.
- std::string::size_type len = strlen(flag);
- if (len < 1) {
+ if (flag.empty()) {
return;
}
-
+ std::string::size_type const len = flag.length();
// Update the string used for the old DEFINITIONS property.
this->RemoveDefineFlag(flag, len, this->DefineFlagsOrig);
@@ -1110,7 +1151,8 @@ void cmMakefile::RemoveDefineFlag(const char* flag)
this->RemoveDefineFlag(flag, len, this->DefineFlags);
}
-void cmMakefile::RemoveDefineFlag(const char* flag, std::string::size_type len,
+void cmMakefile::RemoveDefineFlag(std::string const& flag,
+ std::string::size_type len,
std::string& dflags)
{
// Remove all instances of the flag that are surrounded by
@@ -1127,9 +1169,9 @@ void cmMakefile::RemoveDefineFlag(const char* flag, std::string::size_type len,
}
}
-void cmMakefile::AddCompileOption(const char* option)
+void cmMakefile::AddCompileOption(std::string const& option)
{
- this->AppendProperty("COMPILE_OPTIONS", option);
+ this->AppendProperty("COMPILE_OPTIONS", option.c_str());
}
bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
@@ -1138,14 +1180,14 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove)
static cmsys::RegularExpression valid("^[-/]D[A-Za-z_][A-Za-z0-9_]*(=.*)?$");
// Make sure the definition matches.
- if (!valid.find(def.c_str())) {
+ if (!valid.find(def)) {
return false;
}
// Definitions with non-trivial values require a policy check.
static cmsys::RegularExpression trivial(
"^[-/]D[A-Za-z_][A-Za-z0-9_]*(=[A-Za-z0-9_.]+)?$");
- if (!trivial.find(def.c_str())) {
+ if (!trivial.find(def)) {
// This definition has a non-trivial value.
switch (this->GetPolicyStatus(cmPolicies::CMP0005)) {
case cmPolicies::WARN:
@@ -1367,9 +1409,9 @@ void cmMakefile::Configure()
// make sure the CMakeFiles dir is there
std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary();
filesDir += cmake::GetCMakeFilesDirectory();
- cmSystemTools::MakeDirectory(filesDir.c_str());
+ cmSystemTools::MakeDirectory(filesDir);
- assert(cmSystemTools::FileExists(currentStart.c_str(), true));
+ assert(cmSystemTools::FileExists(currentStart, true));
this->AddDefinition("CMAKE_PARENT_LIST_FILE", currentStart.c_str());
cmListFile listFile;
@@ -1437,8 +1479,8 @@ void cmMakefile::Configure()
if (!hasProject) {
cmListFileFunction project;
project.Name = "PROJECT";
- cmListFileArgument prj("Project", cmListFileArgument::Unquoted, 0);
- project.Arguments.push_back(prj);
+ project.Arguments.emplace_back("Project", cmListFileArgument::Unquoted,
+ 0);
listFile.Functions.insert(listFile.Functions.begin(), project);
}
}
@@ -1530,7 +1572,7 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath,
newSnapshot.GetDirectory().SetCurrentSource(srcPath);
newSnapshot.GetDirectory().SetCurrentBinary(binPath);
- cmSystemTools::MakeDirectory(binPath.c_str());
+ cmSystemTools::MakeDirectory(binPath);
cmMakefile* subMf = new cmMakefile(this->GlobalGenerator, newSnapshot);
this->GetGlobalGenerator()->AddMakefile(subMf);
@@ -1834,7 +1876,7 @@ cmTarget* cmMakefile::AddLibrary(const std::string& lname,
return target;
}
-cmTarget* cmMakefile::AddExecutable(const char* exeName,
+cmTarget* cmMakefile::AddExecutable(const std::string& exeName,
const std::vector<std::string>& srcs,
bool excludeFromAll)
{
@@ -1894,7 +1936,7 @@ cmSourceFile* cmMakefile::GetSourceFileWithOutput(
{
// If the queried path is not absolute we use the backward compatible
// linear-time search for an output with a matching suffix.
- if (!cmSystemTools::FileIsFullPath(name.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(name)) {
return this->LinearGetSourceFileWithOutput(name);
}
// Otherwise we use an efficient lookup map.
@@ -1913,7 +1955,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;
@@ -1923,7 +1965,7 @@ cmSourceGroup* cmMakefile::GetSourceGroup(
if (sg != nullptr) {
// iterate through its children to find match source group
for (unsigned int i = 1; i < name.size(); ++i) {
- sg = sg->LookupChild(name[i].c_str());
+ sg = sg->LookupChild(name[i]);
if (sg == nullptr) {
break;
}
@@ -1967,7 +2009,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name,
if (i == -1) {
// group does not exist nor belong to any existing group
// add its first component
- this->SourceGroups.push_back(cmSourceGroup(name[0].c_str(), regex));
+ this->SourceGroups.push_back(cmSourceGroup(name[0], regex));
sg = this->GetSourceGroup(currentName);
i = 0; // last component found
}
@@ -1977,8 +2019,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 = sg->LookupChild(name[i].c_str());
+ sg->AddChild(cmSourceGroup(name[i], nullptr, sg->GetFullName().c_str()));
+ sg = sg->LookupChild(name[i]);
}
sg->SetGroupRegex(regex);
@@ -2013,7 +2055,7 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name)
* inherited ones.
*/
cmSourceGroup* cmMakefile::FindSourceGroup(
- const char* source, std::vector<cmSourceGroup>& groups) const
+ const std::string& source, std::vector<cmSourceGroup>& groups) const
{
// First search for a group that lists the file explicitly.
for (std::vector<cmSourceGroup>::reverse_iterator sg = groups.rbegin();
@@ -2205,25 +2247,38 @@ bool cmMakefile::PlatformIsx32() const
return false;
}
-bool cmMakefile::PlatformIsAppleIos() const
+cmMakefile::AppleSDK cmMakefile::GetAppleSDKType() const
{
std::string sdkRoot;
sdkRoot = this->GetSafeDefinition("CMAKE_OSX_SYSROOT");
sdkRoot = cmSystemTools::LowerCase(sdkRoot);
- const std::string embedded[] = {
- "appletvos", "appletvsimulator", "iphoneos",
- "iphonesimulator", "watchos", "watchsimulator",
+ struct
+ {
+ std::string name;
+ AppleSDK sdk;
+ } const sdkDatabase[]{
+ { "appletvos", AppleSDK::AppleTVOS },
+ { "appletvsimulator", AppleSDK::AppleTVSimulator },
+ { "iphoneos", AppleSDK::IPhoneOS },
+ { "iphonesimulator", AppleSDK::IPhoneSimulator },
+ { "watchos", AppleSDK::WatchOS },
+ { "watchsimulator", AppleSDK::WatchSimulator },
};
- for (std::string const& i : embedded) {
- if (sdkRoot.find(i) == 0 ||
- sdkRoot.find(std::string("/") + i) != std::string::npos) {
- return true;
+ for (auto entry : sdkDatabase) {
+ if (sdkRoot.find(entry.name) == 0 ||
+ sdkRoot.find(std::string("/") + entry.name) != std::string::npos) {
+ return entry.sdk;
}
}
- return false;
+ return AppleSDK::MacOS;
+}
+
+bool cmMakefile::PlatformIsAppleEmbedded() const
+{
+ return GetAppleSDKType() != AppleSDK::MacOS;
}
const char* cmMakefile::GetSONameFlag(const std::string& language) const
@@ -2237,7 +2292,7 @@ const char* cmMakefile::GetSONameFlag(const std::string& language) const
return GetDefinition(name);
}
-bool cmMakefile::CanIWriteThisFile(const char* fileName) const
+bool cmMakefile::CanIWriteThisFile(std::string const& fileName) const
{
if (!this->IsOn("CMAKE_DISABLE_SOURCE_CHANGES")) {
return true;
@@ -2977,7 +3032,7 @@ bool cmMakefile::ExpandArguments(
for (cmListFileArgument const& i : inArgs) {
// No expansion in a bracket argument.
if (i.Delim == cmListFileArgument::Bracket) {
- outArgs.push_back(cmExpandedCommandArgument(i.Value, true));
+ outArgs.emplace_back(i.Value, true);
continue;
}
// Expand the variables in the argument.
@@ -2988,12 +3043,12 @@ bool cmMakefile::ExpandArguments(
// If the argument is quoted, it should be one argument.
// Otherwise, it may be a list of arguments.
if (i.Delim == cmListFileArgument::Quoted) {
- outArgs.push_back(cmExpandedCommandArgument(value, true));
+ outArgs.emplace_back(value, true);
} else {
std::vector<std::string> stringArgs;
cmSystemTools::ExpandListArgument(value, stringArgs);
for (std::string const& stringArg : stringArgs) {
- outArgs.push_back(cmExpandedCommandArgument(stringArg, false));
+ outArgs.emplace_back(stringArg, false);
}
}
}
@@ -3050,19 +3105,19 @@ std::unique_ptr<cmFunctionBlocker> cmMakefile::RemoveFunctionBlocker(
return std::unique_ptr<cmFunctionBlocker>();
}
-const char* cmMakefile::GetHomeDirectory() const
+std::string const& cmMakefile::GetHomeDirectory() const
{
return this->GetCMakeInstance()->GetHomeDirectory();
}
-const char* cmMakefile::GetHomeOutputDirectory() const
+std::string const& cmMakefile::GetHomeOutputDirectory() const
{
return this->GetCMakeInstance()->GetHomeOutputDirectory();
}
-void cmMakefile::SetScriptModeFile(const char* scriptfile)
+void cmMakefile::SetScriptModeFile(std::string const& scriptfile)
{
- this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile);
+ this->AddDefinition("CMAKE_SCRIPT_MODE_FILE", scriptfile.c_str());
}
void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
@@ -3080,35 +3135,53 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args)
}
}
-cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const
+cmSourceFile* cmMakefile::GetSource(const std::string& sourceName,
+ cmSourceFileLocationKind kind) const
{
- cmSourceFileLocation sfl(this, sourceName);
- for (cmSourceFile* sf : this->SourceFiles) {
- if (sf->Matches(sfl)) {
- return sf;
+ cmSourceFileLocation sfl(this, sourceName, kind);
+ 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;
}
cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName,
- bool generated)
+ bool generated,
+ cmSourceFileLocationKind kind)
{
- cmSourceFile* sf = new cmSourceFile(this, sourceName);
+ cmSourceFile* sf = new cmSourceFile(this, sourceName, kind);
if (generated) {
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;
}
cmSourceFile* cmMakefile::GetOrCreateSource(const std::string& sourceName,
- bool generated)
+ bool generated,
+ cmSourceFileLocationKind kind)
{
- if (cmSourceFile* esf = this->GetSource(sourceName)) {
+ if (cmSourceFile* esf = this->GetSource(sourceName, kind)) {
return esf;
}
- return this->CreateSource(sourceName, generated);
+ return this->CreateSource(sourceName, generated, kind);
}
void cmMakefile::AddTargetObject(std::string const& tgtName,
@@ -3159,7 +3232,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
this->IsSourceFileTryCompile = fast;
// does the binary directory exist ? If not create it...
if (!cmSystemTools::FileIsDirectory(bindir)) {
- cmSystemTools::MakeDirectory(bindir.c_str());
+ cmSystemTools::MakeDirectory(bindir);
}
// change to the tests directory and run cmake
@@ -3186,6 +3259,7 @@ int cmMakefile::TryCompile(const std::string& srcdir,
// do a configure
cm.SetHomeDirectory(srcdir);
cm.SetHomeOutputDirectory(bindir);
+ cm.SetGeneratorInstance(this->GetSafeDefinition("CMAKE_GENERATOR_INSTANCE"));
cm.SetGeneratorPlatform(this->GetSafeDefinition("CMAKE_GENERATOR_PLATFORM"));
cm.SetGeneratorToolset(this->GetSafeDefinition("CMAKE_GENERATOR_TOOLSET"));
cm.LoadCache();
@@ -3336,7 +3410,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
cmSystemTools::ConvertToUnixSlashes(itempl);
itempl += "/";
itempl += filename;
- if (cmSystemTools::FileExists(itempl.c_str())) {
+ if (cmSystemTools::FileExists(itempl)) {
moduleInCMakeModulePath = itempl;
break;
}
@@ -3348,7 +3422,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const
moduleInCMakeRoot += "/Modules/";
moduleInCMakeRoot += filename;
cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot);
- if (!cmSystemTools::FileExists(moduleInCMakeRoot.c_str())) {
+ if (!cmSystemTools::FileExists(moduleInCMakeRoot)) {
moduleInCMakeRoot.clear();
}
@@ -3480,11 +3554,11 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
this->AddCMakeOutputFile(soutfile);
mode_t perm = 0;
- cmSystemTools::GetPermissions(sinfile.c_str(), perm);
+ cmSystemTools::GetPermissions(sinfile, perm);
std::string::size_type pos = soutfile.rfind('/');
if (pos != std::string::npos) {
std::string path = soutfile.substr(0, pos);
- cmSystemTools::MakeDirectory(path.c_str());
+ cmSystemTools::MakeDirectory(path);
}
if (copyonly) {
@@ -3544,7 +3618,7 @@ int cmMakefile::ConfigureFile(const char* infile, const char* outfile,
soutfile.c_str())) {
res = 0;
} else {
- cmSystemTools::SetPermissions(soutfile.c_str(), perm);
+ cmSystemTools::SetPermissions(soutfile, perm);
}
cmSystemTools::RemoveFile(tempOutputFile);
}
@@ -3616,6 +3690,16 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const
return nullptr;
}
+void cmMakefile::GetTests(const std::string& config,
+ std::vector<cmTest*>& tests)
+{
+ for (auto generator : this->GetTestGenerators()) {
+ if (generator->TestsForConfig(config)) {
+ tests.push_back(generator->GetTest());
+ }
+ }
+}
+
void cmMakefile::AddCMakeDependFilesFromUser()
{
std::vector<std::string> deps;
@@ -3623,7 +3707,7 @@ void cmMakefile::AddCMakeDependFilesFromUser()
cmSystemTools::ExpandListArgument(deps_str, deps);
}
for (std::string const& dep : deps) {
- if (cmSystemTools::FileIsFullPath(dep.c_str())) {
+ if (cmSystemTools::FileIsFullPath(dep)) {
this->AddCMakeDependFile(dep);
} else {
std::string f = this->GetCurrentSourceDirectory();
@@ -3980,7 +4064,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id,
// Deprecate old policies, especially those that require a lot
// of code to maintain the old behavior.
- if (status == cmPolicies::OLD && id <= cmPolicies::CMP0036) {
+ if (status == cmPolicies::OLD && id <= cmPolicies::CMP0054) {
this->IssueMessage(cmake::DEPRECATION_WARNING,
cmPolicies::GetPolicyDeprecatedWarning(id));
}
@@ -4133,15 +4217,15 @@ bool cmMakefile::CompileFeatureKnown(cmTarget const* target,
assert(cmGeneratorExpression::Find(feature) == std::string::npos);
bool isCFeature =
- std::find_if(cmArrayBegin(C_FEATURES) + 1, cmArrayEnd(C_FEATURES),
- cmStrCmp(feature)) != cmArrayEnd(C_FEATURES);
+ std::find_if(cm::cbegin(C_FEATURES) + 1, cm::cend(C_FEATURES),
+ cmStrCmp(feature)) != cm::cend(C_FEATURES);
if (isCFeature) {
lang = "C";
return true;
}
bool isCxxFeature =
- std::find_if(cmArrayBegin(CXX_FEATURES) + 1, cmArrayEnd(CXX_FEATURES),
- cmStrCmp(feature)) != cmArrayEnd(CXX_FEATURES);
+ std::find_if(cm::cbegin(CXX_FEATURES) + 1, cm::cend(CXX_FEATURES),
+ cmStrCmp(feature)) != cm::cend(CXX_FEATURES);
if (isCxxFeature) {
lang = "CXX";
return true;
@@ -4230,8 +4314,8 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
// Return true so the caller does not try to lookup the default standard.
return true;
}
- if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
- cmStrCmp(defaultCStandard)) == cmArrayEnd(C_STANDARDS)) {
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
std::ostringstream e;
e << "The CMAKE_C_STANDARD_DEFAULT variable contains an "
"invalid value: \""
@@ -4251,8 +4335,8 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
existingCStandard = defaultCStandard;
}
- if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
- cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
std::ostringstream e;
e << "The C_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCStandard << "\".";
@@ -4261,23 +4345,23 @@ bool cmMakefile::HaveCStandardAvailable(cmTarget const* target,
}
const char* const* existingCIt = existingCStandard
- ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+ ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(existingCStandard))
- : cmArrayEnd(C_STANDARDS);
+ : cm::cend(C_STANDARDS);
if (needC11 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) {
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS), cmStrCmp("11"))) {
return false;
}
if (needC99 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS), cmStrCmp("99"))) {
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS), cmStrCmp("99"))) {
return false;
}
if (needC90 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS), cmStrCmp("90"))) {
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS), cmStrCmp("90"))) {
return false;
}
return true;
@@ -4289,16 +4373,16 @@ bool cmMakefile::IsLaterStandard(std::string const& lang,
{
if (lang == "C") {
const char* const* rhsIt = std::find_if(
- cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS), cmStrCmp(rhs));
+ cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS), cmStrCmp(rhs));
- return std::find_if(rhsIt, cmArrayEnd(C_STANDARDS), cmStrCmp(lhs)) !=
- cmArrayEnd(C_STANDARDS);
+ return std::find_if(rhsIt, cm::cend(C_STANDARDS), cmStrCmp(lhs)) !=
+ cm::cend(C_STANDARDS);
}
const char* const* rhsIt = std::find_if(
- cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS), cmStrCmp(rhs));
+ cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS), cmStrCmp(rhs));
- return std::find_if(rhsIt, cmArrayEnd(CXX_STANDARDS), cmStrCmp(lhs)) !=
- cmArrayEnd(CXX_STANDARDS);
+ return std::find_if(rhsIt, cm::cend(CXX_STANDARDS), cmStrCmp(lhs)) !=
+ cm::cend(CXX_STANDARDS);
}
bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
@@ -4314,9 +4398,8 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
// Return true so the caller does not try to lookup the default standard.
return true;
}
- if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(defaultCxxStandard)) ==
- cmArrayEnd(CXX_STANDARDS)) {
+ if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
std::ostringstream e;
e << "The CMAKE_CXX_STANDARD_DEFAULT variable contains an "
"invalid value: \""
@@ -4337,9 +4420,10 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
existingCxxStandard = defaultCxxStandard;
}
- if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(existingCxxStandard)) ==
- cmArrayEnd(CXX_STANDARDS)) {
+ const char* const* existingCxxLevel =
+ std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(existingCxxStandard));
+ if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
std::ostringstream e;
e << "The CXX_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4347,36 +4431,16 @@ bool cmMakefile::HaveCxxStandardAvailable(cmTarget const* target,
return false;
}
- const char* const* existingCxxIt = existingCxxStandard
- ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(existingCxxStandard))
- : cmArrayEnd(CXX_STANDARDS);
+ /* clang-format off */
+ const char* const* needCxxLevel =
+ needCxx17 ? &CXX_STANDARDS[3]
+ : needCxx14 ? &CXX_STANDARDS[2]
+ : needCxx11 ? &CXX_STANDARDS[1]
+ : needCxx98 ? &CXX_STANDARDS[0]
+ : nullptr;
+ /* clang-format on */
- if (needCxx17 &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("17"))) {
- return false;
- }
- if (needCxx14 &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("14"))) {
- return false;
- }
- if (needCxx11 &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("11"))) {
- return false;
- }
- if (needCxx98 &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("98"))) {
- return false;
- }
- return true;
+ return !needCxxLevel || needCxxLevel <= existingCxxLevel;
}
void cmMakefile::CheckNeededCxxLanguage(const std::string& feature,
@@ -4422,10 +4486,12 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
needCxx17);
const char* existingCxxStandard = target->GetProperty("CXX_STANDARD");
+ const char* const* existingCxxLevel = nullptr;
if (existingCxxStandard) {
- if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(existingCxxStandard)) ==
- cmArrayEnd(CXX_STANDARDS)) {
+ existingCxxLevel =
+ std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(existingCxxStandard));
+ if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
std::ostringstream e;
e << "The CXX_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCxxStandard << "\".";
@@ -4438,51 +4504,51 @@ bool cmMakefile::AddRequiredTargetCxxFeature(cmTarget* target,
return false;
}
}
- const char* const* existingCxxIt = existingCxxStandard
- ? std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
- cmStrCmp(existingCxxStandard))
- : cmArrayEnd(CXX_STANDARDS);
-
- bool setCxx98 = needCxx98 && !existingCxxStandard;
- bool setCxx11 = needCxx11 && !existingCxxStandard;
- bool setCxx14 = needCxx14 && !existingCxxStandard;
- bool setCxx17 = needCxx17 && !existingCxxStandard;
-
- if (needCxx17 && existingCxxStandard &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("17"))) {
- setCxx17 = true;
- } else if (needCxx14 && existingCxxStandard &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("14"))) {
- setCxx14 = true;
- } else if (needCxx11 && existingCxxStandard &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("11"))) {
- setCxx11 = true;
- } else if (needCxx98 && existingCxxStandard &&
- existingCxxIt < std::find_if(cmArrayBegin(CXX_STANDARDS),
- cmArrayEnd(CXX_STANDARDS),
- cmStrCmp("98"))) {
- setCxx98 = true;
- }
-
- if (setCxx17) {
- target->SetProperty("CXX_STANDARD", "17");
- target->SetProperty("CUDA_STANDARD", "17");
- } else if (setCxx14) {
- target->SetProperty("CXX_STANDARD", "14");
- target->SetProperty("CUDA_STANDARD", "14");
- } else if (setCxx11) {
- target->SetProperty("CXX_STANDARD", "11");
- target->SetProperty("CUDA_STANDARD", "11");
- } else if (setCxx98) {
- target->SetProperty("CXX_STANDARD", "98");
- target->SetProperty("CUDA_STANDARD", "98");
+
+ const char* existingCudaStandard = target->GetProperty("CUDA_STANDARD");
+ const char* const* existingCudaLevel = nullptr;
+ if (existingCudaStandard) {
+ existingCudaLevel =
+ std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
+ cmStrCmp(existingCudaStandard));
+ if (existingCudaLevel == cm::cend(CXX_STANDARDS)) {
+ std::ostringstream e;
+ e << "The CUDA_STANDARD property on target \"" << target->GetName()
+ << "\" contained an invalid value: \"" << existingCudaStandard
+ << "\".";
+ if (error) {
+ *error = e.str();
+ } else {
+ this->GetCMakeInstance()->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ this->Backtrace);
+ }
+ return false;
+ }
+ }
+
+ /* clang-format off */
+ const char* const* needCxxLevel =
+ needCxx17 ? &CXX_STANDARDS[3]
+ : needCxx14 ? &CXX_STANDARDS[2]
+ : needCxx11 ? &CXX_STANDARDS[1]
+ : needCxx98 ? &CXX_STANDARDS[0]
+ : nullptr;
+ /* clang-format on */
+
+ if (needCxxLevel) {
+ // Ensure the C++ language level is high enough to support
+ // the needed C++ features.
+ if (!existingCxxLevel || existingCxxLevel < needCxxLevel) {
+ target->SetProperty("CXX_STANDARD", *needCxxLevel);
+ }
+
+ // Ensure the CUDA language level is high enough to support
+ // the needed C++ features.
+ if (!existingCudaLevel || existingCudaLevel < needCxxLevel) {
+ target->SetProperty("CUDA_STANDARD", *needCxxLevel);
+ }
}
+
return true;
}
@@ -4522,8 +4588,8 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
const char* existingCStandard = target->GetProperty("C_STANDARD");
if (existingCStandard) {
- if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
- cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS)) {
+ if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
+ cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
std::ostringstream e;
e << "The C_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCStandard << "\".";
@@ -4537,26 +4603,26 @@ bool cmMakefile::AddRequiredTargetCFeature(cmTarget* target,
}
}
const char* const* existingCIt = existingCStandard
- ? std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
+ ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
cmStrCmp(existingCStandard))
- : cmArrayEnd(C_STANDARDS);
+ : cm::cend(C_STANDARDS);
bool setC90 = needC90 && !existingCStandard;
bool setC99 = needC99 && !existingCStandard;
bool setC11 = needC11 && !existingCStandard;
if (needC11 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS), cmStrCmp("11"))) {
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS), cmStrCmp("11"))) {
setC11 = true;
} else if (needC99 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS),
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS),
cmStrCmp("99"))) {
setC99 = true;
} else if (needC90 && existingCStandard &&
- existingCIt < std::find_if(cmArrayBegin(C_STANDARDS),
- cmArrayEnd(C_STANDARDS),
+ existingCIt < std::find_if(cm::cbegin(C_STANDARDS),
+ cm::cend(C_STANDARDS),
cmStrCmp("90"))) {
setC90 = true;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 0273f5bae..5a30790dc 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -20,6 +20,7 @@
#include "cmListFileCache.h"
#include "cmNewLineStyle.h"
#include "cmPolicies.h"
+#include "cmSourceFileLocationKind.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmTarget.h"
@@ -165,9 +166,9 @@ public:
/**
* Add a define flag to the build.
*/
- void AddDefineFlag(const char* definition);
- void RemoveDefineFlag(const char* definition);
- void AddCompileOption(const char* option);
+ void AddDefineFlag(std::string const& definition);
+ void RemoveDefineFlag(std::string const& definition);
+ void AddCompileOption(std::string const& option);
/** Create a new imported target with the name and type given. */
cmTarget* AddImportedTarget(const std::string& name,
@@ -179,16 +180,23 @@ public:
/**
* Add an executable to the build.
*/
- cmTarget* AddExecutable(const char* exename,
+ cmTarget* AddExecutable(const std::string& exename,
const std::vector<std::string>& srcs,
bool excludeFromAll = false);
+ /** Where the target originated from. */
+ enum class TargetOrigin
+ {
+ Project,
+ Generator
+ };
+
/**
- * Add a utility to the build. A utiltity target is a command that
+ * Add a utility to the build. A utility target is a command that
* is run every time the target is built.
*/
cmTarget* AddUtilityCommand(const std::string& utilityName,
- bool excludeFromAll,
+ TargetOrigin origin, bool excludeFromAll,
const std::vector<std::string>& depends,
const char* workingDirectory,
const char* command, const char* arg1 = nullptr,
@@ -196,13 +204,13 @@ public:
const char* arg3 = nullptr,
const char* arg4 = nullptr);
cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
const char* workingDirectory, const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
const char* comment = nullptr, bool uses_terminal = false,
bool command_expand_lists = false);
cmTarget* AddUtilityCommand(
- const std::string& utilityName, bool excludeFromAll,
+ const std::string& utilityName, TargetOrigin origin, bool excludeFromAll,
const char* workingDirectory, const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines, bool escapeOldStyle = true,
@@ -301,13 +309,13 @@ public:
bool IgnoreErrorsCMP0061() const;
- const char* GetHomeDirectory() const;
- const char* GetHomeOutputDirectory() const;
+ std::string const& GetHomeDirectory() const;
+ std::string const& GetHomeOutputDirectory() const;
/**
* Set CMAKE_SCRIPT_MODE_FILE variable when running a -P script.
*/
- void SetScriptModeFile(const char* scriptfile);
+ void SetScriptModeFile(std::string const& scriptfile);
/**
* Set CMAKE_ARGC, CMAKE_ARGV0 ... variables.
@@ -380,22 +388,26 @@ public:
/** Get a cmSourceFile pointer for a given source name, if the name is
* not found, then a null pointer is returned.
*/
- cmSourceFile* GetSource(const std::string& sourceName) const;
+ cmSourceFile* GetSource(
+ const std::string& sourceName,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous) const;
/** Create the source file and return it. generated
* indicates if it is a generated file, this is used in determining
* how to create the source file instance e.g. name
*/
- cmSourceFile* CreateSource(const std::string& sourceName,
- bool generated = false);
+ cmSourceFile* CreateSource(
+ const std::string& sourceName, bool generated = false,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
/** Get a cmSourceFile pointer for a given source name, if the name is
* not found, then create the source file and return it. generated
* indicates if it is a generated file, this is used in determining
* how to create the source file instance e.g. name
*/
- cmSourceFile* GetOrCreateSource(const std::string& sourceName,
- bool generated = false);
+ cmSourceFile* GetOrCreateSource(
+ const std::string& sourceName, bool generated = false,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
void AddTargetObject(std::string const& tgtName, std::string const& objFile);
@@ -432,8 +444,23 @@ public:
/** Return whether the target platform is x32. */
bool PlatformIsx32() const;
+ /** Apple SDK Type */
+ enum class AppleSDK
+ {
+ MacOS,
+ IPhoneOS,
+ IPhoneSimulator,
+ AppleTVOS,
+ AppleTVSimulator,
+ WatchOS,
+ WatchSimulator,
+ };
+
+ /** What SDK type points CMAKE_OSX_SYSROOT to? */
+ AppleSDK GetAppleSDKType() const;
+
/** Return whether the target platform is Apple iOS. */
- bool PlatformIsAppleIos() const;
+ bool PlatformIsAppleEmbedded() const;
/** Retrieve soname flag for the specified language if supported */
const char* GetSONameFlag(const std::string& language) const;
@@ -446,7 +473,7 @@ public:
/**
* Make sure CMake can write this file
*/
- bool CanIWriteThisFile(const char* fileName) const;
+ bool CanIWriteThisFile(std::string const& fileName) const;
#if defined(CMAKE_BUILD_WITH_CMAKE)
/**
@@ -489,7 +516,7 @@ public:
/**
* find what source group this source is in
*/
- cmSourceGroup* FindSourceGroup(const char* source,
+ cmSourceGroup* FindSourceGroup(const std::string& source,
std::vector<cmSourceGroup>& groups) const;
#endif
@@ -561,7 +588,7 @@ public:
bool atOnly, bool escapeQuotes) const;
/**
- * Copy file but change lines acording to ConfigureString
+ * Copy file but change lines according to ConfigureString
*/
int ConfigureFile(const char* infile, const char* outfile, bool copyonly,
bool atOnly, bool escapeQuotes,
@@ -639,6 +666,11 @@ public:
cmTest* GetTest(const std::string& testName) const;
/**
+ * Get all tests that run under the given configuration.
+ */
+ void GetTests(const std::string& config, std::vector<cmTest*>& tests);
+
+ /**
* Return a location of a file in cmake or custom modules directory
*/
std::string GetModulesFile(const char* name) const;
@@ -665,6 +697,10 @@ public:
{
return this->InstallGenerators;
}
+ const std::vector<cmInstallGenerator*>& GetInstallGenerators() const
+ {
+ return this->InstallGenerators;
+ }
void AddTestGenerator(cmTestGenerator* g)
{
@@ -737,6 +773,9 @@ public:
/** Set whether or not to report a CMP0000 violation. */
void SetCheckCMP0000(bool b) { this->CheckCMP0000 = b; }
+ bool CheckCMP0037(std::string const& targetName,
+ cmStateEnums::TargetType targetType) const;
+
cmStringRange GetIncludeDirectoriesEntries() const;
cmBacktraceRange GetIncludeDirectoriesBacktraces() const;
cmStringRange GetCompileOptionsEntries() const;
@@ -793,7 +832,7 @@ public:
void RemoveExportBuildFileGeneratorCMP0024(cmExportBuildFileGenerator* gen);
void AddExportBuildFileGenerator(cmExportBuildFileGenerator* gen);
- // Maintain a stack of pacakge names to determine the depth of find modules
+ // Maintain a stack of package names to determine the depth of find modules
// we are currently being called with
std::deque<std::string> FindPackageModuleStack;
@@ -809,7 +848,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;
@@ -828,8 +878,9 @@ protected:
std::string DefineFlags;
// Track the value of the computed DEFINITIONS property.
- void AddDefineFlag(const char*, std::string&);
- void RemoveDefineFlag(const char*, std::string::size_type, std::string&);
+ void AddDefineFlag(std::string const& flag, std::string&);
+ void RemoveDefineFlag(std::string const& flag, std::string::size_type,
+ std::string&);
std::string DefineFlagsOrig;
#if defined(CMAKE_BUILD_WITH_CMAKE)
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 801f72ab6..9bbc04337 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -69,9 +69,6 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
this->WriteExecutableRule(true);
}
- // Write the requires target.
- this->WriteTargetRequiresRules();
-
// Write clean target
this->WriteTargetCleanRules();
@@ -329,28 +326,28 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
outpath = this->Makefile->GetCurrentBinaryDirectory();
outpath += cmake::GetCMakeFilesDirectory();
outpath += "/CMakeRelink.dir";
- cmSystemTools::MakeDirectory(outpath.c_str());
+ cmSystemTools::MakeDirectory(outpath);
outpath += "/";
if (!targetNameImport.empty()) {
outpathImp = outpath;
}
} else {
- cmSystemTools::MakeDirectory(outpath.c_str());
+ cmSystemTools::MakeDirectory(outpath);
if (!targetNameImport.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
- cmSystemTools::MakeDirectory(outpathImp.c_str());
+ cmSystemTools::MakeDirectory(outpathImp);
outpathImp += "/";
}
}
std::string compilePdbOutputPath =
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
+ cmSystemTools::MakeDirectory(compilePdbOutputPath);
std::string pdbOutputPath =
this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+ cmSystemTools::MakeDirectory(pdbOutputPath);
pdbOutputPath += "/";
std::string targetFullPath = outpath + targetName;
@@ -620,7 +617,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
cmakeCommand += " -E __run_co_compile --lwyu=";
cmakeCommand += targetOutPathReal;
- real_link_commands.push_back(cmakeCommand);
+ real_link_commands.push_back(std::move(cmakeCommand));
}
std::string launcher;
@@ -669,7 +666,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
symlink += targetOutPathReal;
symlink += " ";
symlink += targetOutPath;
- commands1.push_back(symlink);
+ commands1.push_back(std::move(symlink));
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 80c62d10f..9299ffe33 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -89,9 +89,6 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
break;
}
- // Write the requires target.
- this->WriteTargetRequiresRules();
-
// Write clean target
this->WriteTargetCleanRules();
@@ -528,30 +525,30 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
outpath = this->Makefile->GetCurrentBinaryDirectory();
outpath += cmake::GetCMakeFilesDirectory();
outpath += "/CMakeRelink.dir";
- cmSystemTools::MakeDirectory(outpath.c_str());
+ cmSystemTools::MakeDirectory(outpath);
outpath += "/";
if (!targetNameImport.empty()) {
outpathImp = outpath;
}
} else {
outpath = this->GeneratorTarget->GetDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(outpath.c_str());
+ cmSystemTools::MakeDirectory(outpath);
outpath += "/";
if (!targetNameImport.empty()) {
outpathImp = this->GeneratorTarget->GetDirectory(
this->ConfigName, cmStateEnums::ImportLibraryArtifact);
- cmSystemTools::MakeDirectory(outpathImp.c_str());
+ cmSystemTools::MakeDirectory(outpathImp);
outpathImp += "/";
}
}
std::string compilePdbOutputPath =
this->GeneratorTarget->GetCompilePDBDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(compilePdbOutputPath.c_str());
+ cmSystemTools::MakeDirectory(compilePdbOutputPath);
std::string pdbOutputPath =
this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
- cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+ cmSystemTools::MakeDirectory(pdbOutputPath);
pdbOutputPath += "/";
std::string targetFullPath = outpath + targetName;
@@ -900,7 +897,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string cmd = launcher + acc;
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
cmd, vars);
- real_link_commands.push_back(cmd);
+ real_link_commands.push_back(std::move(cmd));
}
}
// Append to the archive with the other object sets.
@@ -910,7 +907,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
std::string cmd = launcher + aac;
rulePlaceholderExpander->ExpandRuleVariables(this->LocalGenerator,
cmd, vars);
- real_link_commands.push_back(cmd);
+ real_link_commands.push_back(std::move(cmd));
}
}
// Finish the archive.
@@ -921,7 +918,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
vars);
// If there is no ranlib the command will be ":". Skip it.
if (!cmd.empty() && cmd[0] != ':') {
- real_link_commands.push_back(cmd);
+ real_link_commands.push_back(std::move(cmd));
}
}
} else {
@@ -934,7 +931,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
cmakeCommand += " -E __run_co_compile --lwyu=";
cmakeCommand += targetOutPathReal;
- real_link_commands.push_back(cmakeCommand);
+ real_link_commands.push_back(std::move(cmakeCommand));
}
// Expand placeholders.
@@ -975,7 +972,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
symlink += targetOutPathSO;
symlink += " ";
symlink += targetOutPath;
- commands1.push_back(symlink);
+ commands1.push_back(std::move(symlink));
this->LocalGenerator->CreateCDCommand(
commands1, this->Makefile->GetCurrentBinaryDirectory(),
this->LocalGenerator->GetBinaryDirectory());
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 7db010c24..73cf1f0fb 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -89,7 +89,7 @@ void cmMakefileTargetGenerator::CreateRuleFile()
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
this->TargetBuildDirectoryFull =
this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
- cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
+ cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull);
// Construct the rule file name.
this->BuildFileName = this->TargetBuildDirectory;
@@ -200,10 +200,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include any dependencies generated for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator
- ->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull)
- .c_str())
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), dependFileNameFull))
<< "\n\n";
if (!this->NoRuleMessages) {
@@ -212,16 +210,14 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include the progress variables for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator
- ->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
- this->ProgressFileNameFull)
- .c_str())
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->ProgressFileNameFull))
<< "\n\n";
}
// make sure the depend file exists
- if (!cmSystemTools::FileExists(dependFileNameFull.c_str())) {
+ if (!cmSystemTools::FileExists(dependFileNameFull)) {
// Write an empty dependency file.
cmGeneratedFileStream depFileStream(
dependFileNameFull.c_str(), false,
@@ -250,11 +246,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
<< "# Include the compile flags for this target's objects.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator
- ->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
- this->FlagFileNameFull)
- .c_str())
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), this->FlagFileNameFull))
<< "\n\n";
}
@@ -327,7 +320,7 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
copyCommand += " ";
copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
output, cmOutputConverter::SHELL);
- commands.push_back(copyCommand);
+ commands.push_back(std::move(copyCommand));
this->Generator->LocalGenerator->WriteMakeRule(
*this->Generator->BuildFileStream, nullptr, output, depends, commands,
false);
@@ -368,8 +361,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
// Create the directory containing the object file. This may be a
// subdirectory under the target's directory.
std::string dir = cmSystemTools::GetFilenamePath(obj);
- cmSystemTools::MakeDirectory(
- this->LocalGenerator->ConvertToFullPath(dir).c_str());
+ cmSystemTools::MakeDirectory(this->LocalGenerator->ConvertToFullPath(dir));
// Save this in the target's list of object files.
this->Objects.push_back(obj);
@@ -425,6 +417,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
std::string config = this->LocalGenerator->GetConfigName();
std::string configUpper = cmSystemTools::UpperCase(config);
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, this->GeneratorTarget, config,
+ this->GeneratorTarget->GetName(), lang);
// Add Fortran format flags.
if (lang == "Fortran") {
@@ -432,34 +427,62 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
// Add flags from source file properties.
- if (const char* cflags = source.GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
- const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
- false, this->GeneratorTarget);
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = source.GetProperty(COMPILE_FLAGS)) {
+ const char* evaluatedFlags =
+ genexInterpreter.Evaluate(cflags, COMPILE_FLAGS);
this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
*this->FlagFileStream << "# Custom flags: " << relativeObj
<< "_FLAGS = " << evaluatedFlags << "\n"
<< "\n";
}
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = source.GetProperty(COMPILE_OPTIONS)) {
+ const char* evaluatedOptions =
+ genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS);
+ this->LocalGenerator->AppendCompileOptions(flags, evaluatedOptions);
+ *this->FlagFileStream << "# Custom options: " << relativeObj
+ << "_OPTIONS = " << evaluatedOptions << "\n"
+ << "\n";
+ }
+
+ // Add include directories from source file properties.
+ std::vector<std::string> includes;
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = source.GetProperty(INCLUDE_DIRECTORIES)) {
+ const char* evaluatedIncludes =
+ genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
+ this->LocalGenerator->AppendIncludeDirectories(includes, evaluatedIncludes,
+ source);
+ *this->FlagFileStream << "# Custom include directories: " << relativeObj
+ << "_INCLUDE_DIRECTORIES = " << evaluatedIncludes
+ << "\n"
+ << "\n";
+ }
+
// Add language-specific defines.
std::set<std::string> defines;
- // Add source-sepcific preprocessor definitions.
- if (const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS")) {
- this->LocalGenerator->AppendDefines(defines, compile_defs);
+ // Add source-specific preprocessor definitions.
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* compile_defs = source.GetProperty(COMPILE_DEFINITIONS)) {
+ const char* evaluatedDefs =
+ genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS);
+ this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
*this->FlagFileStream << "# Custom defines: " << relativeObj
- << "_DEFINES = " << compile_defs << "\n"
+ << "_DEFINES = " << evaluatedDefs << "\n"
<< "\n";
}
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
if (const char* config_compile_defs = source.GetProperty(defPropName)) {
- this->LocalGenerator->AppendDefines(defines, config_compile_defs);
+ const char* evaluatedDefs =
+ genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS);
+ this->LocalGenerator->AppendDefines(defines, evaluatedDefs);
*this->FlagFileStream << "# Custom defines: " << relativeObj << "_DEFINES_"
- << configUpper << " = " << config_compile_defs
- << "\n"
+ << configUpper << " = " << evaluatedDefs << "\n"
<< "\n";
}
@@ -559,7 +582,10 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
vars.Defines = definesString.c_str();
- std::string const includesString = "$(" + lang + "_INCLUDES)";
+ std::string includesString = this->LocalGenerator->GetIncludeFlags(
+ includes, this->GeneratorTarget, lang, true, false, config);
+ this->LocalGenerator->AppendFlags(includesString,
+ "$(" + lang + "_INCLUDES)");
vars.Includes = includesString.c_str();
// At the moment, it is assumed that C, C++, Fortran, and CUDA have both
@@ -657,8 +683,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
}
// Maybe insert a compiler launcher like ccache or distcc
- if (!compileCommands.empty() &&
- (lang == "C" || lang == "CXX" || lang == "CUDA")) {
+ if (!compileCommands.empty() && (lang == "C" || lang == "CXX" ||
+ lang == "Fortran" || lang == "CUDA")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
const char* clauncher =
this->GeneratorTarget->GetProperty(clauncher_prop);
@@ -763,7 +789,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
} else {
std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
cmd += preprocessRuleVar;
- commands.push_back(cmd);
+ commands.push_back(std::move(cmd));
}
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
@@ -810,7 +836,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
} else {
std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
cmd += assemblyRuleVar;
- commands.push_back(cmd);
+ commands.push_back(std::move(cmd));
}
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
@@ -818,65 +844,6 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
commands, false);
}
}
-
- // If the language needs provides-requires mode, create the
- // corresponding targets.
- std::string objectRequires = relativeObj;
- objectRequires += ".requires";
- std::vector<std::string> p_depends;
- // always provide an empty requires target
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
- objectRequires, p_depends, no_commands,
- true);
-
- // write a build rule to recursively build what this obj provides
- std::string objectProvides = relativeObj;
- objectProvides += ".provides";
- std::string temp = relativeObj;
- temp += ".provides.build";
- std::vector<std::string> r_commands;
- std::string tgtMakefileName =
- this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
- tgtMakefileName += "/build.make";
- r_commands.push_back(
- this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(), temp));
-
- p_depends.clear();
- p_depends.push_back(objectRequires);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
- objectProvides, p_depends, r_commands,
- true);
-
- // write the provides.build rule dependency on the obj file
- p_depends.clear();
- p_depends.push_back(relativeObj);
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr, temp,
- p_depends, no_commands, false);
-}
-
-void cmMakefileTargetGenerator::WriteTargetRequiresRules()
-{
- std::vector<std::string> depends;
- std::vector<std::string> no_commands;
-
- // Construct the name of the dependency generation target.
- std::string depTarget =
- this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
- depTarget += "/requires";
-
- // This target drives dependency generation for all object files.
- std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
- std::string objTarget;
- for (std::string const& obj : this->Objects) {
- objTarget = relPath;
- objTarget += obj;
- objTarget += ".requires";
- depends.push_back(objTarget);
- }
-
- // Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
- depTarget, depends, no_commands, true);
}
void cmMakefileTargetGenerator::WriteTargetCleanRules()
@@ -937,7 +904,7 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
for (std::vector<std::string>::const_iterator o = outputs.begin() + 1;
o != outputs.end(); ++o) {
// Touch the extra output so "make" knows that it was updated,
- // but only if the output was acually created.
+ // but only if the output was actually created.
std::string const out = this->LocalGenerator->ConvertToOutputFormat(
this->LocalGenerator->MaybeConvertToRelativePath(binDir, *o),
cmOutputConverter::SHELL);
@@ -1370,12 +1337,12 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
std::vector<std::string>& depends)
{
// Add dependencies on the compiled object files.
- std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
- std::string objTarget;
+ std::string const& relPath =
+ this->LocalGenerator->GetHomeRelativeOutputPath();
for (std::string const& obj : this->Objects) {
- objTarget = relPath;
+ std::string objTarget = relPath;
objTarget += obj;
- depends.push_back(objTarget);
+ depends.push_back(std::move(objTarget));
}
// Add dependencies on the external object files.
@@ -1466,8 +1433,8 @@ void cmMakefileTargetGenerator::CreateLinkScript(
this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
cmOutputConverter::SHELL);
link_command += " --verbose=$(VERBOSE)";
- makefile_commands.push_back(link_command);
- makefile_depends.push_back(linkScriptName);
+ makefile_commands.push_back(std::move(link_command));
+ makefile_depends.push_back(std::move(linkScriptName));
}
bool cmMakefileTargetGenerator::CheckUseResponseFileForObjects(
@@ -1539,7 +1506,7 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
// Add a dependency so the target will rebuild when the set of
// objects changes.
- makefile_depends.push_back(responseFileNameFull);
+ makefile_depends.push_back(std::move(responseFileNameFull));
// Construct the name to be used on the command line.
std::string responseFileName = this->TargetBuildDirectory;
@@ -1678,10 +1645,17 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
}
if (useResponseFile) {
+ std::string const responseFlagVar =
+ "CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
+ std::string responseFlag =
+ this->Makefile->GetSafeDefinition(responseFlagVar);
+ if (responseFlag.empty()) {
+ responseFlag = "@";
+ }
std::string name = "includes_";
name += lang;
name += ".rsp";
- std::string arg = "@" +
+ std::string arg = std::move(responseFlag) +
this->CreateResponseFile(name.c_str(), includeFlags,
this->FlagFileDepends[lang]);
this->LocalGenerator->AppendFlags(flags, arg);
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 5ab7e36b0..7af3cf39e 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -63,9 +63,6 @@ protected:
void WriteCommonCodeRules();
void WriteTargetLanguageFlags();
- // write the provide require rules for this target
- void WriteTargetRequiresRules();
-
// write the clean rules for this target
void WriteTargetCleanRules();
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 46df0d89c..8fbd5d2bd 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -4,6 +4,7 @@
#include <ostream>
#include <string>
+#include <utility>
#include <vector>
#include "cmGeneratedFileStream.h"
@@ -45,11 +46,9 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
<< "# Include the progress variables for this target.\n"
<< this->GlobalGenerator->IncludeDirective << " " << root
<< cmSystemTools::ConvertToOutputPath(
- this->LocalGenerator
- ->MaybeConvertToRelativePath(
- this->LocalGenerator->GetBinaryDirectory(),
- this->ProgressFileNameFull)
- .c_str())
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->ProgressFileNameFull))
<< "\n\n";
}
@@ -90,7 +89,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
if (depends.empty() && commands.empty()) {
std::string hack = this->GlobalGenerator->GetEmptyRuleHackDepends();
if (!hack.empty()) {
- depends.push_back(hack);
+ depends.push_back(std::move(hack));
}
}
diff --git a/Source/cmMessageCommand.cxx b/Source/cmMessageCommand.cxx
index 43fb5f54c..5a341bd2b 100644
--- a/Source/cmMessageCommand.cxx
+++ b/Source/cmMessageCommand.cxx
@@ -63,7 +63,7 @@ bool cmMessageCommand::InitialPass(std::vector<std::string> const& args,
std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
if (type != cmake::MESSAGE) {
- // we've overriden the message type, above, so display it directly
+ // we've overridden the message type, above, so display it directly
cmMessenger* m = this->Makefile->GetMessenger();
m->DisplayMessage(type, message, this->Makefile->GetBacktrace());
} else {
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index e0cc35a15..ddbc772fe 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -498,13 +498,12 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
cmakeCommand += " -E __run_co_compile --lwyu=";
cmGeneratorTarget& gt = *this->GetGeneratorTarget();
const std::string cfgName = this->GetConfigName();
- std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
std::string targetOutputReal = this->ConvertToNinjaPath(
gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
/*realname=*/true));
cmakeCommand += targetOutputReal;
cmakeCommand += " || true";
- linkCmds.push_back(cmakeCommand);
+ linkCmds.push_back(std::move(cmakeCommand));
}
return linkCmds;
}
@@ -686,16 +685,11 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
}
}
- cmNinjaDeps byproducts;
-
if (!this->TargetNameImport.empty()) {
const std::string impLibPath = localGen.ConvertToOutputFormat(
targetOutputImplib, cmOutputConverter::SHELL);
vars["TARGET_IMPLIB"] = impLibPath;
EnsureParentDirectoryExists(impLibPath);
- if (genTarget.HasImportLibrary()) {
- byproducts.push_back(targetOutputImplib);
- }
}
const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
@@ -713,29 +707,6 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
std::replace(link_path.begin(), link_path.end(), '\\', '/');
}
- const std::vector<cmCustomCommand>* cmdLists[3] = {
- &genTarget.GetPreBuildCommands(), &genTarget.GetPreLinkCommands(),
- &genTarget.GetPostBuildCommands()
- };
-
- std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
- vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines);
- vars["POST_BUILD"] = localGen.BuildCommandLine(postBuildCmdLines);
-
- std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
- &preLinkCmdLines,
- &postBuildCmdLines };
-
- for (unsigned i = 0; i != 3; ++i) {
- for (cmCustomCommand const& cc : *cmdLists[i]) {
- cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator());
- localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
- std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
- std::transform(ccByproducts.begin(), ccByproducts.end(),
- std::back_inserter(byproducts), MapToNinjaPath());
- }
- }
-
cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();
// Device linking currently doesn't support response files so
@@ -760,7 +731,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
/*implicitOuts=*/cmNinjaDeps(), explicitDeps,
implicitDeps, orderOnlyDeps, vars, rspfile,
commandLineLengthLimit, &usedResponseFile);
- this->WriteDeviceLinkRule(usedResponseFile);
+ this->WriteDeviceLinkRule(false);
}
void cmNinjaNormalTargetGenerator::WriteLinkStatement()
@@ -978,7 +949,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
std::string obj_list_file = mdi->DefFile + ".objs";
cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
obj_list_file, cmOutputConverter::SHELL);
- preLinkCmdLines.push_back(cmd);
+ preLinkCmdLines.push_back(std::move(cmd));
// create a list of obj files for the -E __create_def to read
cmGeneratedFileStream fout(obj_list_file.c_str());
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 5805259a5..f4faf47a2 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -135,13 +135,21 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject(
}
// Add source file specific flags.
- if (const char* cflags = source->GetProperty("COMPILE_FLAGS")) {
- std::string config = this->LocalGenerator->GetConfigName();
- cmGeneratorExpression ge;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(cflags);
- const char* evaluatedFlags = cge->Evaluate(this->LocalGenerator, config,
- false, this->GeneratorTarget);
- this->LocalGenerator->AppendFlags(flags, evaluatedFlags);
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, this->GeneratorTarget,
+ this->LocalGenerator->GetConfigName(), this->GeneratorTarget->GetName(),
+ language);
+
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = source->GetProperty(COMPILE_FLAGS)) {
+ this->LocalGenerator->AppendFlags(
+ flags, genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
+ }
+
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = source->GetProperty(COMPILE_OPTIONS)) {
+ this->LocalGenerator->AppendCompileOptions(
+ flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
return flags;
@@ -178,13 +186,23 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
const std::string& language)
{
std::set<std::string> defines;
- this->LocalGenerator->AppendDefines(
- defines, source->GetProperty("COMPILE_DEFINITIONS"));
- {
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += cmSystemTools::UpperCase(this->GetConfigName());
- this->LocalGenerator->AppendDefines(defines,
- source->GetProperty(defPropName));
+ const std::string config = this->LocalGenerator->GetConfigName();
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, this->GeneratorTarget, config,
+ this->GeneratorTarget->GetName(), language);
+
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
+ if (const char* compile_defs = source->GetProperty(COMPILE_DEFINITIONS)) {
+ this->LocalGenerator->AppendDefines(
+ defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS));
+ }
+
+ std::string defPropName = "COMPILE_DEFINITIONS_";
+ defPropName += cmSystemTools::UpperCase(config);
+ if (const char* config_compile_defs = source->GetProperty(defPropName)) {
+ this->LocalGenerator->AppendDefines(
+ defines,
+ genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS));
}
std::string definesString = this->GetDefines(language);
@@ -193,6 +211,30 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
return definesString;
}
+std::string cmNinjaTargetGenerator::ComputeIncludes(
+ cmSourceFile const* source, const std::string& language)
+{
+ std::vector<std::string> includes;
+ const std::string config = this->LocalGenerator->GetConfigName();
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, this->GeneratorTarget, config,
+ this->GeneratorTarget->GetName(), language);
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = source->GetProperty(INCLUDE_DIRECTORIES)) {
+ this->LocalGenerator->AppendIncludeDirectories(
+ includes, genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES),
+ *source);
+ }
+
+ std::string includesString = this->LocalGenerator->GetIncludeFlags(
+ includes, this->GeneratorTarget, language, true, false, config);
+ this->LocalGenerator->AppendFlags(includesString,
+ this->GetIncludes(language));
+
+ return includesString;
+}
+
cmNinjaDeps cmNinjaTargetGenerator::ComputeLinkDeps() const
{
// Static libraries never depend on other targets for linking.
@@ -405,14 +447,20 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
std::string flags = "$FLAGS";
std::string rspfile;
std::string rspcontent;
- std::string responseFlag;
bool const lang_supports_response = !(lang == "RC" || lang == "CUDA");
if (lang_supports_response && this->ForceResponseFile()) {
+ std::string const responseFlagVar =
+ "CMAKE_" + lang + "_RESPONSE_FILE_FLAG";
+ std::string responseFlag =
+ this->Makefile->GetSafeDefinition(responseFlagVar);
+ if (responseFlag.empty()) {
+ responseFlag = "@";
+ }
rspfile = "$RSP_FILE";
- responseFlag = "@" + rspfile;
+ responseFlag += rspfile;
rspcontent = " $DEFINES $INCLUDES $FLAGS";
- flags = responseFlag;
+ flags = std::move(responseFlag);
vars.Defines = "";
vars.Includes = "";
}
@@ -647,7 +695,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
// Maybe insert a compiler launcher like ccache or distcc
if (!compileCmds.empty() &&
- (lang == "C" || lang == "CXX" || lang == "CUDA")) {
+ (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) {
std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER";
const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop);
if (clauncher && *clauncher) {
@@ -807,7 +855,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
cmNinjaVars vars;
vars["FLAGS"] = this->ComputeFlagsForObject(source, language);
vars["DEFINES"] = this->ComputeDefines(source, language);
- vars["INCLUDES"] = this->GetIncludes(language);
+ vars["INCLUDES"] = this->ComputeIncludes(source, language);
if (!this->NeedDepTypeMSVC(language)) {
vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
objectFileName + ".d", cmOutputConverter::SHELL);
@@ -1035,7 +1083,7 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string escapedSourceFileName = sourceFileName;
- if (!cmSystemTools::FileIsFullPath(sourceFileName.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(sourceFileName)) {
escapedSourceFileName = cmSystemTools::CollapseFullPath(
escapedSourceFileName, this->GetGlobalGenerator()
->GetCMakeInstance()
@@ -1095,8 +1143,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
void cmNinjaTargetGenerator::EnsureDirectoryExists(
const std::string& path) const
{
- if (cmSystemTools::FileIsFullPath(path.c_str())) {
- cmSystemTools::MakeDirectory(path.c_str());
+ if (cmSystemTools::FileIsFullPath(path)) {
+ cmSystemTools::MakeDirectory(path);
} else {
cmGlobalNinjaGenerator* gg = this->GetGlobalGenerator();
std::string fullPath =
@@ -1104,7 +1152,7 @@ void cmNinjaTargetGenerator::EnsureDirectoryExists(
// Also ensures their is a trailing slash.
gg->StripNinjaOutputPathPrefixAsSuffix(fullPath);
fullPath += path;
- cmSystemTools::MakeDirectory(fullPath.c_str());
+ cmSystemTools::MakeDirectory(fullPath);
}
}
@@ -1140,7 +1188,7 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
output);
// Add as a dependency to the target so that it gets called.
- this->Generator->ExtraFiles.push_back(output);
+ this->Generator->ExtraFiles.push_back(std::move(output));
}
void cmNinjaTargetGenerator::addPoolNinjaVariable(
diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h
index 770a99d7f..4660a3ae8 100644
--- a/Source/cmNinjaTargetGenerator.h
+++ b/Source/cmNinjaTargetGenerator.h
@@ -82,6 +82,9 @@ protected:
std::string ComputeDefines(cmSourceFile const* source,
const std::string& language);
+ std::string ComputeIncludes(cmSourceFile const* source,
+ const std::string& language);
+
std::string ConvertToNinjaPath(const std::string& path) const
{
return this->GetGlobalGenerator()->ConvertToNinjaPath(path);
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index c85c82d84..2b9678596 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -43,7 +43,7 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
out += "/";
out += this->GT->GetAppBundleDirectory(this->ConfigName,
cmGeneratorTarget::FullLevel);
- cmSystemTools::MakeDirectory(out.c_str());
+ cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
@@ -82,7 +82,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
// Configure the Info.plist file
std::string plist = newoutpath;
- if (!this->Makefile->PlatformIsAppleIos()) {
+ if (!this->Makefile->PlatformIsAppleEmbedded()) {
// Put the Info.plist file into the Resources directory.
this->MacContentFolders->insert("Resources");
plist += "/Resources";
@@ -93,7 +93,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
plist.c_str());
// Generate Versions directory only for MacOSX frameworks
- if (this->Makefile->PlatformIsAppleIos()) {
+ if (this->Makefile->PlatformIsAppleEmbedded()) {
return;
}
@@ -105,10 +105,10 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
// Make foo.framework/Versions
std::string versions = contentdir;
versions += "Versions";
- cmSystemTools::MakeDirectory(versions.c_str());
+ cmSystemTools::MakeDirectory(versions);
// Make foo.framework/Versions/version
- cmSystemTools::MakeDirectory(newoutpath.c_str());
+ cmSystemTools::MakeDirectory(newoutpath);
// Current -> version
oldName = frameworkVersion;
@@ -173,7 +173,7 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
out += "/";
out += this->GT->GetCFBundleDirectory(this->ConfigName,
cmGeneratorTarget::FullLevel);
- cmSystemTools::MakeDirectory(out.c_str());
+ cmSystemTools::MakeDirectory(out);
this->Makefile->AddCMakeOutputFile(out);
// Configure the Info.plist file. Note that it needs the executable name
@@ -213,7 +213,7 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
macdir += "/";
macdir += pkgloc;
- cmSystemTools::MakeDirectory(macdir.c_str());
+ cmSystemTools::MakeDirectory(macdir);
// Record use of this content location. Only the first level
// directory is needed.
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 27ad71037..04a931854 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -118,7 +118,7 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
std::string file = dir;
file += "/";
file += name;
- if (cmSystemTools::FileExists(file.c_str(), true)) {
+ if (cmSystemTools::FileExists(file, true)) {
// The file conflicts only if it is not the same as the original
// file due to a symlink or hardlink.
return !cmSystemTools::SameFile(this->FullPath, file);
diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx
index dac656912..25db92943 100644
--- a/Source/cmOutputConverter.cxx
+++ b/Source/cmOutputConverter.cxx
@@ -29,7 +29,7 @@ std::string cmOutputConverter::ConvertToOutputForExisting(
// space.
if (this->GetState()->UseWindowsShell() &&
remote.find(' ') != std::string::npos &&
- cmSystemTools::FileExists(remote.c_str())) {
+ cmSystemTools::FileExists(remote)) {
std::string tmp;
if (cmSystemTools::GetShortPath(remote, tmp)) {
return this->ConvertToOutputFormat(tmp, format);
@@ -125,7 +125,7 @@ std::string cmOutputConverter::ForceToRelativePath(
assert(local_path.empty() || local_path[local_path.size() - 1] != '/');
// If the path is already relative then just return the path.
- if (!cmSystemTools::FileIsFullPath(remote_path.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(remote_path)) {
return remote_path;
}
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index cde90375f..bdb98cad5 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -173,7 +173,7 @@ protected:
std::string line;
while (cmSystemTools::GetLineFromStream(fin, line)) {
- if (cmHasLiteralPrefix(line.c_str(), "#include")) {
+ if (cmHasLiteralPrefix(line, "#include")) {
// if it is an include line then create a string class
size_t qstart = line.find('\"', 8);
size_t qend;
@@ -213,51 +213,51 @@ protected:
cxxFile = root + ".cxx";
bool found = false;
// try jumping to .cxx .cpp and .c in order
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
for (std::string path : this->IncludeDirectories) {
path = path + "/";
path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ if (cmSystemTools::FileExists(path)) {
found = true;
}
}
if (!found) {
cxxFile = root + ".cpp";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
for (std::string path : this->IncludeDirectories) {
path = path + "/";
path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ if (cmSystemTools::FileExists(path)) {
found = true;
}
}
}
if (!found) {
cxxFile = root + ".c";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
for (std::string path : this->IncludeDirectories) {
path = path + "/";
path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ if (cmSystemTools::FileExists(path)) {
found = true;
}
}
}
if (!found) {
cxxFile = root + ".txx";
- if (cmSystemTools::FileExists(cxxFile.c_str())) {
+ if (cmSystemTools::FileExists(cxxFile)) {
found = true;
}
for (std::string path : this->IncludeDirectories) {
path = path + "/";
path = path + cxxFile;
- if (cmSystemTools::FileExists(path.c_str())) {
+ if (cmSystemTools::FileExists(path)) {
found = true;
}
}
@@ -426,7 +426,7 @@ protected:
path = path + "/";
}
path = path + fname;
- if (cmSystemTools::FileExists(path.c_str(), true) &&
+ if (cmSystemTools::FileExists(path, true) &&
!cmSystemTools::FileIsDirectory(path)) {
std::string fp = cmSystemTools::CollapseFullPath(path);
this->DirectoryToFileToPathMap[extraPath ? extraPath : ""][fname] = fp;
@@ -440,7 +440,7 @@ protected:
path = path + "/";
}
path = path + fname;
- if (cmSystemTools::FileExists(path.c_str(), true) &&
+ if (cmSystemTools::FileExists(path, true) &&
!cmSystemTools::FileIsDirectory(path)) {
std::string fp = cmSystemTools::CollapseFullPath(path);
this->DirectoryToFileToPathMap[extraPath][fname] = fp;
diff --git a/Source/cmParseArgumentsCommand.cxx b/Source/cmParseArgumentsCommand.cxx
index 0922e6e24..9a5b09721 100644
--- a/Source/cmParseArgumentsCommand.cxx
+++ b/Source/cmParseArgumentsCommand.cxx
@@ -71,8 +71,8 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
typedef std::map<std::string, std::string> single_map;
typedef std::map<std::string, std::vector<std::string>> multi_map;
options_map options;
- single_map single;
- multi_map multi;
+ single_map singleValArgs;
+ multi_map multiValArgs;
// anything else is put into a vector of unparsed strings
std::vector<std::string> unparsed;
@@ -98,7 +98,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
if (!used_keywords.insert(iter).second) {
this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter);
}
- single[iter]; // default initialize
+ singleValArgs[iter]; // default initialize
}
// the fourth argument is a (cmake) list of multi argument options
@@ -108,7 +108,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
if (!used_keywords.insert(iter).second) {
this->GetMakefile()->IssueMessage(cmake::WARNING, dup_warning + iter);
}
- multi[iter]; // default initialize
+ multiValArgs[iter]; // default initialize
}
enum insideValues
@@ -161,15 +161,15 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
continue;
}
- const single_map::iterator singleIter = single.find(arg);
- if (singleIter != single.end()) {
+ const single_map::iterator singleIter = singleValArgs.find(arg);
+ if (singleIter != singleValArgs.end()) {
insideValues = SINGLE;
currentArgName = arg;
continue;
}
- const multi_map::iterator multiIter = multi.find(arg);
- if (multiIter != multi.end()) {
+ const multi_map::iterator multiIter = multiValArgs.find(arg);
+ if (multiIter != multiValArgs.end()) {
insideValues = MULTI;
currentArgName = arg;
continue;
@@ -177,14 +177,14 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
switch (insideValues) {
case SINGLE:
- single[currentArgName] = arg;
+ singleValArgs[currentArgName] = arg;
insideValues = NONE;
break;
case MULTI:
if (parseFromArgV) {
- multi[currentArgName].push_back(escape_arg(arg));
+ multiValArgs[currentArgName].push_back(escape_arg(arg));
} else {
- multi[currentArgName].push_back(arg);
+ multiValArgs[currentArgName].push_back(arg);
}
break;
default:
@@ -204,7 +204,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
this->Makefile->AddDefinition(prefix + iter.first,
iter.second ? "TRUE" : "FALSE");
}
- for (auto const& iter : single) {
+ for (auto const& iter : singleValArgs) {
if (!iter.second.empty()) {
this->Makefile->AddDefinition(prefix + iter.first, iter.second.c_str());
} else {
@@ -212,7 +212,7 @@ bool cmParseArgumentsCommand::InitialPass(std::vector<std::string> const& args,
}
}
- for (auto const& iter : multi) {
+ for (auto const& iter : multiValArgs) {
if (!iter.second.empty()) {
this->Makefile->AddDefinition(
prefix + iter.first, cmJoin(cmMakeRange(iter.second), ";").c_str());
diff --git a/Source/cmPipeConnection.cxx b/Source/cmPipeConnection.cxx
index 9e565f60a..3dab2f075 100644
--- a/Source/cmPipeConnection.cxx
+++ b/Source/cmPipeConnection.cxx
@@ -2,6 +2,8 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmPipeConnection.h"
+#include <algorithm>
+
#include "cmServer.h"
cmPipeConnection::cmPipeConnection(const std::string& name,
@@ -13,39 +15,33 @@ cmPipeConnection::cmPipeConnection(const std::string& name,
void cmPipeConnection::Connect(uv_stream_t* server)
{
- if (this->ClientPipe) {
+ if (this->WriteStream.get()) {
// Accept and close all pipes but the first:
- uv_pipe_t* rejectPipe = new uv_pipe_t();
+ cm::uv_pipe_ptr rejectPipe;
+
+ rejectPipe.init(*this->Server->GetLoop(), 0);
+ uv_accept(server, rejectPipe);
- uv_pipe_init(this->Server->GetLoop(), rejectPipe, 0);
- uv_accept(server, reinterpret_cast<uv_stream_t*>(rejectPipe));
- uv_close(reinterpret_cast<uv_handle_t*>(rejectPipe),
- &on_close_delete<uv_pipe_t>);
return;
}
- this->ClientPipe = new uv_pipe_t();
- uv_pipe_init(this->Server->GetLoop(), this->ClientPipe, 0);
- this->ClientPipe->data = static_cast<cmEventBasedConnection*>(this);
- auto client = reinterpret_cast<uv_stream_t*>(this->ClientPipe);
- if (uv_accept(server, client) != 0) {
- uv_close(reinterpret_cast<uv_handle_t*>(client),
- &on_close_delete<uv_pipe_t>);
- this->ClientPipe = nullptr;
+ cm::uv_pipe_ptr ClientPipe;
+ ClientPipe.init(*this->Server->GetLoop(), 0,
+ static_cast<cmEventBasedConnection*>(this));
+
+ if (uv_accept(server, ClientPipe) != 0) {
return;
}
- this->ReadStream = client;
- this->WriteStream = client;
- uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
+ uv_read_start(ClientPipe, on_alloc_buffer, on_read);
+ WriteStream = std::move(ClientPipe);
Server->OnConnected(this);
}
bool cmPipeConnection::OnServeStart(std::string* errorMessage)
{
- this->ServerPipe = new uv_pipe_t();
- uv_pipe_init(this->Server->GetLoop(), this->ServerPipe, 0);
- this->ServerPipe->data = static_cast<cmEventBasedConnection*>(this);
+ this->ServerPipe.init(*this->Server->GetLoop(), 0,
+ static_cast<cmEventBasedConnection*>(this));
int r;
if ((r = uv_pipe_bind(this->ServerPipe, this->PipeName.c_str())) != 0) {
@@ -53,8 +49,8 @@ bool cmPipeConnection::OnServeStart(std::string* errorMessage)
": " + uv_err_name(r);
return false;
}
- auto serverStream = reinterpret_cast<uv_stream_t*>(this->ServerPipe);
- if ((r = uv_listen(serverStream, 1, on_new_connection)) != 0) {
+
+ if ((r = uv_listen(this->ServerPipe, 1, on_new_connection)) != 0) {
*errorMessage = std::string("Internal Error listening on ") +
this->PipeName + ": " + uv_err_name(r);
return false;
@@ -65,18 +61,11 @@ bool cmPipeConnection::OnServeStart(std::string* errorMessage)
bool cmPipeConnection::OnConnectionShuttingDown()
{
- if (this->ClientPipe) {
- uv_close(reinterpret_cast<uv_handle_t*>(this->ClientPipe),
- &on_close_delete<uv_pipe_t>);
+ if (this->WriteStream.get()) {
this->WriteStream->data = nullptr;
}
- uv_close(reinterpret_cast<uv_handle_t*>(this->ServerPipe),
- &on_close_delete<uv_pipe_t>);
- this->ClientPipe = nullptr;
- this->ServerPipe = nullptr;
- this->WriteStream = nullptr;
- this->ReadStream = nullptr;
+ this->ServerPipe.reset();
return cmEventBasedConnection::OnConnectionShuttingDown();
}
diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h
index 7b8984296..49f9fdf8a 100644
--- a/Source/cmPipeConnection.h
+++ b/Source/cmPipeConnection.h
@@ -4,6 +4,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmUVHandlePtr.h"
#include <string>
#include "cmConnection.h"
@@ -23,6 +24,5 @@ public:
private:
const std::string PipeName;
- uv_pipe_t* ServerPipe = nullptr;
- uv_pipe_t* ClientPipe = nullptr;
+ cm::uv_pipe_ptr ServerPipe;
};
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 6c33e2b0f..c39f927c5 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) \
@@ -225,6 +228,7 @@ class cmMakefile;
F(CMP0021) \
F(CMP0022) \
F(CMP0027) \
+ F(CMP0037) \
F(CMP0038) \
F(CMP0041) \
F(CMP0042) \
diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx
index 617e1ca7d..83717061f 100644
--- a/Source/cmProcessOutput.cxx
+++ b/Source/cmProcessOutput.cxx
@@ -13,7 +13,7 @@ cmProcessOutput::Encoding cmProcessOutput::FindEncoding(
std::string const& name)
{
Encoding encoding = Auto;
- if (name == "UTF8") {
+ if ((name == "UTF8") || (name == "UTF-8")) {
encoding = UTF8;
} else if (name == "NONE") {
encoding = None;
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index fea8a9dde..dfa185888 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -98,7 +98,7 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
} else if (args[i] == "DESCRIPTION") {
if (haveDescription) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "DESCRITPION may be specified at most once.");
+ cmake::FATAL_ERROR, "DESCRIPTION may be specified at most once.");
cmSystemTools::SetFatalErrorOccured();
return true;
}
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index ae1fdfae2..09cc63a40 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -7,6 +7,8 @@
#include "cmSourceFile.h"
#include "cmSystemTools.h"
+#include <utility>
+
class cmExecutionStatus;
// cmQTWrapCPPCommand
@@ -45,7 +47,7 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
// Compute the name of the header from which to generate the file.
std::string hname;
- if (cmSystemTools::FileIsFullPath(j->c_str())) {
+ if (cmSystemTools::FileIsFullPath(*j)) {
hname = *j;
} else {
if (curr && curr->GetPropertyAsBool("GENERATED")) {
@@ -71,7 +73,7 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
commandLine.push_back(hname);
cmCustomCommandLines commandLines;
- commandLines.push_back(commandLine);
+ commandLines.push_back(std::move(commandLine));
std::vector<std::string> depends;
depends.push_back(moc_exe);
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 3d586d6bd..da36cdf43 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -7,6 +7,8 @@
#include "cmSourceFile.h"
#include "cmSystemTools.h"
+#include <utility>
+
class cmExecutionStatus;
// cmQTWrapUICommand
@@ -53,7 +55,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
// Compute the name of the ui file from which to generate others.
std::string uiName;
- if (cmSystemTools::FileIsFullPath(j->c_str())) {
+ if (cmSystemTools::FileIsFullPath(*j)) {
uiName = *j;
} else {
if (curr && curr->GetPropertyAsBool("GENERATED")) {
@@ -86,7 +88,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
hCommand.push_back(hName);
hCommand.push_back(uiName);
cmCustomCommandLines hCommandLines;
- hCommandLines.push_back(hCommand);
+ hCommandLines.push_back(std::move(hCommand));
cmCustomCommandLine cxxCommand;
cxxCommand.push_back(uic_exe);
@@ -96,7 +98,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
cxxCommand.push_back(cxxName);
cxxCommand.push_back(uiName);
cmCustomCommandLines cxxCommandLines;
- cxxCommandLines.push_back(cxxCommand);
+ cxxCommandLines.push_back(std::move(cxxCommand));
cmCustomCommandLine mocCommand;
mocCommand.push_back(moc_exe);
@@ -104,7 +106,7 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
mocCommand.push_back(mocName);
mocCommand.push_back(hName);
cmCustomCommandLines mocCommandLines;
- mocCommandLines.push_back(mocCommand);
+ mocCommandLines.push_back(std::move(mocCommand));
std::vector<std::string> depends;
depends.push_back(uiName);
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index 0fc2fc012..6e9ca443f 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -2,15 +2,13 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmQtAutoGen.h"
#include "cmAlgorithms.h"
-#include "cmProcessOutput.h"
#include "cmSystemTools.h"
-#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
+#include <iterator>
#include <sstream>
-#include <stddef.h>
// - Static variables
@@ -19,10 +17,6 @@ std::string const genNameMoc = "AutoMoc";
std::string const genNameUic = "AutoUic";
std::string const genNameRcc = "AutoRcc";
-std::string const mcNameSingle = "SINGLE";
-std::string const mcNameWrap = "WRAP";
-std::string const mcNameFull = "FULL";
-
// - Static functions
/// @brief Merges newOpts into baseOpts
@@ -79,221 +73,31 @@ 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,
- std::vector<std::string>& files,
- std::string* errorMessage)
-{
- bool allGood = true;
- // Read qrc file content into string
- std::string qrcContents;
- {
- cmsys::ifstream ifs(fileName.c_str());
- if (ifs) {
- std::ostringstream osst;
- osst << ifs.rdbuf();
- qrcContents = osst.str();
- } else {
- if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc file not readable:\n"
- << " " << cmQtAutoGen::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
- }
- allGood = false;
- }
- }
- if (allGood) {
- // qrc file directory
- std::string qrcDir(cmSystemTools::GetFilenamePath(fileName));
- if (!qrcDir.empty()) {
- qrcDir += '/';
- }
-
- cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
- cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
-
- size_t offset = 0;
- while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
- std::string qrcEntry = fileMatchRegex.match(1);
- offset += qrcEntry.size();
- {
- fileReplaceRegex.find(qrcEntry);
- std::string tag = fileReplaceRegex.match(1);
- qrcEntry = qrcEntry.substr(tag.size());
- }
- if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
- qrcEntry = qrcDir + qrcEntry;
- }
- files.push_back(qrcEntry);
- }
- }
- return allGood;
-}
-
-/// @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::string const& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage)
-{
- if (rccCommand.empty()) {
- cmSystemTools::Error("rcc executable not available");
- 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);
-
- // Run rcc list command
- bool result = false;
- int retVal = 0;
- std::string rccStdOut;
- std::string rccStdErr;
- {
- std::vector<std::string> command;
- command.push_back(rccCommand);
- command.push_back(hasDashDashList ? "--list" : "-list");
- command.push_back(fileNameName);
- result = cmSystemTools::RunSingleCommand(
- command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
- cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto);
- }
- 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();
- }
- return false;
- }
-
- // Parse rcc std output
- {
- std::istringstream ostr(rccStdOut);
- std::string oline;
- while (std::getline(ostr, oline)) {
- oline = utilStripCR(oline);
- if (!oline.empty()) {
- files.push_back(oline);
- }
- }
- }
- // Parse rcc error output
- {
- std::istringstream estr(rccStdErr);
- std::string eline;
- while (std::getline(estr, eline)) {
- eline = utilStripCR(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();
- }
- return false;
- }
- pos += searchString.length();
- std::string::size_type sz = eline.size() - pos - 1;
- files.push_back(eline.substr(pos, sz));
- }
- }
- }
-
- // Convert relative paths to absolute paths
- for (std::string& resFile : files) {
- resFile = cmSystemTools::CollapseCombinedPath(fileDir, resFile);
- }
-
- return true;
-}
-
// - Class definitions
-std::string const cmQtAutoGen::listSep = "<<<S>>>";
+std::string const cmQtAutoGen::ListSep = "<<<S>>>";
+unsigned int const cmQtAutoGen::ParallelMax = 64;
-std::string const& cmQtAutoGen::GeneratorName(Generator type)
+std::string const& cmQtAutoGen::GeneratorName(GeneratorT type)
{
switch (type) {
- case Generator::GEN:
+ case GeneratorT::GEN:
return genNameGen;
- case Generator::MOC:
+ case GeneratorT::MOC:
return genNameMoc;
- case Generator::UIC:
+ case GeneratorT::UIC:
return genNameUic;
- case Generator::RCC:
+ case GeneratorT::RCC:
return genNameRcc;
}
return genNameGen;
}
-std::string cmQtAutoGen::GeneratorNameUpper(Generator genType)
+std::string cmQtAutoGen::GeneratorNameUpper(GeneratorT genType)
{
return cmSystemTools::UpperCase(cmQtAutoGen::GeneratorName(genType));
}
-std::string const& cmQtAutoGen::MultiConfigName(MultiConfig config)
-{
- switch (config) {
- case MultiConfig::SINGLE:
- return mcNameSingle;
- case MultiConfig::WRAP:
- return mcNameWrap;
- case MultiConfig::FULL:
- return mcNameFull;
- }
- return mcNameWrap;
-}
-
-cmQtAutoGen::MultiConfig cmQtAutoGen::MultiConfigType(std::string const& name)
-{
- if (name == mcNameSingle) {
- return MultiConfig::SINGLE;
- }
- if (name == mcNameFull) {
- return MultiConfig::FULL;
- }
- return MultiConfig::WRAP;
-}
-
std::string cmQtAutoGen::Quoted(std::string const& text)
{
static const char* rep[18] = { "\\", "\\\\", "\"", "\\\"", "\a", "\\a",
@@ -301,8 +105,7 @@ std::string cmQtAutoGen::Quoted(std::string const& text)
"\r", "\\r", "\t", "\\t", "\v", "\\v" };
std::string res = text;
- for (const char* const* it = cmArrayBegin(rep); it != cmArrayEnd(rep);
- it += 2) {
+ for (const char* const* it = cm::cbegin(rep); it != cm::cend(rep); it += 2) {
cmSystemTools::ReplaceString(res, *it, *(it + 1));
}
res = '"' + res;
@@ -310,6 +113,33 @@ std::string cmQtAutoGen::Quoted(std::string const& text)
return res;
}
+std::string cmQtAutoGen::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;
+}
+
+std::string cmQtAutoGen::SubDirPrefix(std::string const& filename)
+{
+ std::string res(cmSystemTools::GetFilenamePath(filename));
+ if (!res.empty()) {
+ res += '/';
+ }
+ return res;
+}
+
std::string cmQtAutoGen::AppendFilenameSuffix(std::string const& filename,
std::string const& suffix)
{
@@ -349,26 +179,79 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts,
MergeOptions(baseOpts, newOpts, valueOpts, isQt5);
}
-bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion,
- std::string const& rccCommand,
- std::string const& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage)
+void cmQtAutoGen::RccListParseContent(std::string const& content,
+ std::vector<std::string>& files)
{
- bool allGood = false;
- if (cmSystemTools::FileExists(fileName.c_str())) {
- if (qtMajorVersion == "4") {
- allGood = RccListInputsQt4(fileName, files, errorMessage);
- } else {
- allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage);
+ cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
+ cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
+
+ const char* contentChars = content.c_str();
+ while (fileMatchRegex.find(contentChars)) {
+ std::string const qrcEntry = fileMatchRegex.match(1);
+ contentChars += qrcEntry.size();
+ {
+ fileReplaceRegex.find(qrcEntry);
+ std::string const tag = fileReplaceRegex.match(1);
+ files.push_back(qrcEntry.substr(tag.size()));
}
- } else {
- if (errorMessage != nullptr) {
- std::ostringstream ost;
- ost << "rcc file does not exist:\n"
- << " " << cmQtAutoGen::Quoted(fileName) << "\n";
- *errorMessage = ost.str();
+ }
+}
+
+bool cmQtAutoGen::RccListParseOutput(std::string const& rccStdOut,
+ std::string const& rccStdErr,
+ std::vector<std::string>& files,
+ std::string& error)
+{
+ // 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)) {
+ StripCR(oline);
+ if (!oline.empty()) {
+ files.push_back(oline);
+ }
+ }
+ }
+ // Parse rcc error output
+ {
+ std::istringstream estr(rccStdErr);
+ std::string eline;
+ while (std::getline(estr, eline)) {
+ StripCR(eline);
+ if (cmHasLiteralPrefix(eline, "RCC: Error in")) {
+ static std::string const searchString = "Cannot find file '";
+
+ std::string::size_type pos = eline.find(searchString);
+ if (pos == std::string::npos) {
+ error = "rcc lists unparsable output:\n";
+ error += cmQtAutoGen::Quoted(eline);
+ error += "\n";
+ return false;
+ }
+ pos += searchString.length();
+ std::string::size_type sz = eline.size() - pos - 1;
+ files.push_back(eline.substr(pos, sz));
+ }
+ }
+ }
+
+ return true;
+}
+
+void cmQtAutoGen::RccListConvertFullPath(std::string const& qrcFileDir,
+ std::vector<std::string>& files)
+{
+ for (std::string& entry : files) {
+ std::string tmp = cmSystemTools::CollapseCombinedPath(qrcFileDir, entry);
+ entry = std::move(tmp);
}
- return allGood;
}
diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h
index acc092fb3..67f61b197 100644
--- a/Source/cmQtAutoGen.h
+++ b/Source/cmQtAutoGen.h
@@ -9,14 +9,18 @@
#include <vector>
/** \class cmQtAutoGen
- * \brief Class used as namespace for QtAutogen related types and functions
+ * \brief Common base class for QtAutoGen classes
*/
class cmQtAutoGen
{
public:
- static std::string const listSep;
+ /// @brief Nested lists separator
+ static std::string const ListSep;
+ /// @brief Maximum number of parallel threads/processes in a generator
+ static unsigned int const ParallelMax;
- enum Generator
+ /// @brief AutoGen generator type
+ enum class GeneratorT
{
GEN, // General
MOC,
@@ -24,27 +28,20 @@ public:
RCC
};
- enum MultiConfig
- {
- SINGLE, // Single configuration
- WRAP, // Multi configuration using wrapper files
- FULL // Full multi configuration using per config sources
- };
-
public:
/// @brief Returns the generator name
- static std::string const& GeneratorName(Generator genType);
+ static std::string const& GeneratorName(GeneratorT genType);
/// @brief Returns the generator name in upper case
- static std::string GeneratorNameUpper(Generator genType);
-
- /// @brief Returns the multi configuration name string
- static std::string const& MultiConfigName(MultiConfig config);
- /// @brief Returns the multi configuration type
- static MultiConfig MultiConfigType(std::string const& name);
+ static std::string GeneratorNameUpper(GeneratorT genType);
/// @brief Returns a the string escaped and enclosed in quotes
static std::string Quoted(std::string const& text);
+ static std::string QuotedCommand(std::vector<std::string> const& command);
+
+ /// @brief Returns the parent directory of the file with a "/" suffix
+ static std::string SubDirPrefix(std::string const& filename);
+
/// @brief Appends the suffix to the filename before the last dot
static std::string AppendFilenameSuffix(std::string const& filename,
std::string const& suffix);
@@ -59,14 +56,21 @@ public:
std::vector<std::string> const& newOpts,
bool isQt5);
- /// @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,
- std::string const& fileName,
- std::vector<std::string>& files,
- std::string* errorMessage = nullptr);
+ /// @brief Parses the content of a qrc file
+ ///
+ /// Use when rcc does not support the "--list" option
+ static void RccListParseContent(std::string const& content,
+ std::vector<std::string>& files);
+
+ /// @brief Parses the output of the "rcc --list ..." command
+ static bool RccListParseOutput(std::string const& rccStdOut,
+ std::string const& rccStdErr,
+ std::vector<std::string>& files,
+ std::string& error);
+
+ /// @brief Converts relative qrc entry paths to full paths
+ static void RccListConvertFullPath(std::string const& qrcFileDir,
+ std::vector<std::string>& files);
};
#endif
diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h
deleted file mode 100644
index 677c39792..000000000
--- 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/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
new file mode 100644
index 000000000..93c78b5bd
--- /dev/null
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -0,0 +1,1393 @@
+/* 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 "cmQtAutoGenInitializer.h"
+
+#include "cmAlgorithms.h"
+#include "cmCustomCommand.h"
+#include "cmCustomCommandLines.h"
+#include "cmDuration.h"
+#include "cmFilePathChecksum.h"
+#include "cmGeneratedFileStream.h"
+#include "cmGeneratorTarget.h"
+#include "cmGlobalGenerator.h"
+#include "cmLinkItem.h"
+#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
+#include "cmOutputConverter.h"
+#include "cmPolicies.h"
+#include "cmProcessOutput.h"
+#include "cmSourceFile.h"
+#include "cmSourceGroup.h"
+#include "cmState.h"
+#include "cmStateTypes.h"
+#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmake.h"
+#include "cmsys/FStream.hxx"
+#include "cmsys/SystemInformation.hxx"
+
+#include <algorithm>
+#include <array>
+#include <deque>
+#include <map>
+#include <set>
+#include <sstream>
+#include <string>
+#include <utility>
+#include <vector>
+
+inline static const char* SafeString(const char* value)
+{
+ return (value != nullptr) ? value : "";
+}
+
+inline static std::string GetSafeProperty(cmGeneratorTarget const* target,
+ const char* key)
+{
+ return std::string(SafeString(target->GetProperty(key)));
+}
+
+inline static std::string GetSafeProperty(cmSourceFile const* sf,
+ const char* key)
+{
+ return std::string(SafeString(sf->GetProperty(key)));
+}
+
+static std::size_t GetParallelCPUCount()
+{
+ static std::size_t count = 0;
+ // Detect only on the first call
+ if (count == 0) {
+ cmsys::SystemInformation info;
+ info.RunCPUCheck();
+ count = info.GetNumberOfPhysicalCPU();
+ count = std::max<std::size_t>(count, 1);
+ count = std::min<std::size_t>(count, cmQtAutoGen::ParallelMax);
+ }
+ return count;
+}
+
+static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
+ cmQtAutoGen::GeneratorT genType)
+{
+ cmSourceGroup* sourceGroup = nullptr;
+ // Acquire source group
+ {
+ std::string property;
+ std::string groupName;
+ {
+ std::array<std::string, 2> props;
+ // Use generator specific group name
+ switch (genType) {
+ case cmQtAutoGen::GeneratorT::MOC:
+ props[0] = "AUTOMOC_SOURCE_GROUP";
+ break;
+ case cmQtAutoGen::GeneratorT::RCC:
+ props[0] = "AUTORCC_SOURCE_GROUP";
+ break;
+ default:
+ props[0] = "AUTOGEN_SOURCE_GROUP";
+ break;
+ }
+ props[1] = "AUTOGEN_SOURCE_GROUP";
+ for (std::string& prop : props) {
+ const char* propName = makefile->GetState()->GetGlobalProperty(prop);
+ if ((propName != nullptr) && (*propName != '\0')) {
+ groupName = propName;
+ property = std::move(prop);
+ break;
+ }
+ }
+ }
+ // Generate a source group on demand
+ if (!groupName.empty()) {
+ sourceGroup = makefile->GetOrCreateSourceGroup(groupName);
+ if (sourceGroup == nullptr) {
+ std::ostringstream ost;
+ ost << cmQtAutoGen::GeneratorNameUpper(genType);
+ ost << ": " << property;
+ ost << ": Could not find or create the source group ";
+ ost << cmQtAutoGen::Quoted(groupName);
+ cmSystemTools::Error(ost.str().c_str());
+ return false;
+ }
+ }
+ }
+ if (sourceGroup != nullptr) {
+ sourceGroup->AddGroupFile(fileName);
+ }
+ return true;
+}
+
+static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
+{
+ makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),
+ false);
+}
+
+static std::string FileProjectRelativePath(cmMakefile* makefile,
+ std::string const& fileName)
+{
+ std::string res;
+ {
+ std::string pSource = cmSystemTools::RelativePath(
+ makefile->GetCurrentSourceDirectory(), fileName);
+ std::string pBinary = cmSystemTools::RelativePath(
+ makefile->GetCurrentBinaryDirectory(), fileName);
+ if (pSource.size() < pBinary.size()) {
+ res = std::move(pSource);
+ } else if (pBinary.size() < fileName.size()) {
+ res = std::move(pBinary);
+ } else {
+ res = fileName;
+ }
+ }
+ return res;
+}
+
+/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
+ * recursive STATIC_LIBRARY dependencies depends on targetOrigin
+ * (STATIC_LIBRARY cycle).
+ */
+static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
+ cmGeneratorTarget const* targetDepend,
+ std::string const& config)
+{
+ bool cycle = false;
+ if ((targetOrigin->GetType() == cmStateEnums::STATIC_LIBRARY) &&
+ (targetDepend->GetType() == cmStateEnums::STATIC_LIBRARY)) {
+ std::set<cmGeneratorTarget const*> knownLibs;
+ std::deque<cmGeneratorTarget const*> testLibs;
+
+ // Insert initial static_library dependency
+ knownLibs.insert(targetDepend);
+ testLibs.push_back(targetDepend);
+
+ while (!testLibs.empty()) {
+ cmGeneratorTarget const* testTarget = testLibs.front();
+ testLibs.pop_front();
+ // Check if the test target is the origin target (cycle)
+ if (testTarget == targetOrigin) {
+ cycle = true;
+ break;
+ }
+ // Collect all static_library dependencies from the test target
+ cmLinkImplementationLibraries const* libs =
+ testTarget->GetLinkImplementationLibraries(config);
+ if (libs != nullptr) {
+ for (cmLinkItem const& item : libs->Libraries) {
+ cmGeneratorTarget const* depTarget = item.Target;
+ if ((depTarget != nullptr) &&
+ (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&
+ knownLibs.insert(depTarget).second) {
+ testLibs.push_back(depTarget);
+ }
+ }
+ }
+ }
+ }
+ return cycle;
+}
+
+cmQtAutoGenInitializer::cmQtAutoGenInitializer(
+ cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled,
+ std::string const& qtVersionMajor)
+ : Target(target)
+ , MocEnabled(mocEnabled)
+ , UicEnabled(uicEnabled)
+ , RccEnabled(rccEnabled)
+ , MultiConfig(false)
+ , QtVersionMajor(qtVersionMajor)
+{
+ this->QtVersionMinor =
+ cmQtAutoGenInitializer::GetQtMinorVersion(target, this->QtVersionMajor);
+}
+
+void cmQtAutoGenInitializer::InitCustomTargets()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator();
+
+ // Configurations
+ this->MultiConfig = globalGen->IsMultiConfig();
+ this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList);
+ if (this->ConfigsList.empty()) {
+ this->ConfigsList.push_back(this->ConfigDefault);
+ }
+
+ // Autogen target name
+ this->AutogenTargetName = this->Target->GetName();
+ this->AutogenTargetName += "_autogen";
+
+ // Autogen directories
+ {
+ // 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;
+ }
+ cmSystemTools::ConvertToUnixSlashes(this->DirBuild);
+
+ // Working directory
+ this->DirWork = cbd;
+ cmSystemTools::ConvertToUnixSlashes(this->DirWork);
+ }
+
+ // Autogen files
+ {
+ this->AutogenInfoFile = this->DirInfo;
+ this->AutogenInfoFile += "/AutogenInfo.cmake";
+
+ this->AutogenSettingsFile = this->DirInfo;
+ this->AutogenSettingsFile += "/AutogenOldSettings.txt";
+ }
+
+ // Autogen target FOLDER property
+ {
+ const char* folder =
+ makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER");
+ if (folder == nullptr) {
+ folder =
+ makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER");
+ }
+ // Inherit FOLDER property from target (#13688)
+ if (folder == nullptr) {
+ folder = SafeString(this->Target->Target->GetProperty("FOLDER"));
+ }
+ if (folder != nullptr) {
+ this->AutogenFolder = folder;
+ }
+ }
+
+ std::set<std::string> autogenDependFiles;
+ std::set<cmTarget*> autogenDependTargets;
+ std::vector<std::string> autogenProvides;
+
+ // Remove build directories on cleanup
+ AddCleanFile(makefile, this->DirBuild);
+ // Remove old settings on cleanup
+ {
+ std::string base = this->DirInfo;
+ base += "/AutogenOldSettings";
+ if (this->MultiConfig) {
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string filename = base;
+ filename += '_';
+ filename += cfg;
+ filename += ".cmake";
+ AddCleanFile(makefile, filename);
+ }
+ } else {
+ AddCleanFile(makefile, base.append(".cmake"));
+ }
+ }
+
+ // Add moc compilation to generated files list
+ if (this->MocEnabled) {
+ std::string mocsComp = this->DirBuild + "/mocs_compilation.cpp";
+ this->AddGeneratedSource(mocsComp, GeneratorT::MOC);
+ autogenProvides.push_back(std::move(mocsComp));
+ }
+
+ // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES
+ if (this->MocEnabled || this->UicEnabled ||
+ (this->RccEnabled && this->MultiConfig)) {
+ std::string includeDir = this->DirBuild;
+ includeDir += "/include";
+ if (this->MultiConfig) {
+ includeDir += "_$<CONFIG>";
+ }
+ 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, cmDuration::zero(), 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
+ std::vector<std::string> generatedSources;
+ std::vector<std::string> generatedHeaders;
+ {
+ std::string const qrcExt = "qrc";
+ std::vector<cmSourceFile*> srcFiles;
+ this->Target->GetConfigCommonSourceFiles(srcFiles);
+ for (cmSourceFile* sf : srcFiles) {
+ if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
+ continue;
+ }
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ std::string const& fPath = sf->GetFullPath();
+ std::string const& ext = sf->GetExtension();
+ // Register generated files that will be scanned by moc or uic
+ 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 ((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 {
+ this->Headers.push_back(absPath);
+ }
+ } else {
+ if (generated) {
+ generatedSources.push_back(absPath);
+ } else {
+ this->Sources.push_back(absPath);
+ }
+ }
+ }
+ }
+ }
+ // Register rcc enabled files
+ if (this->RccEnabled && (ext == qrcExt) &&
+ !sf->GetPropertyAsBool("SKIP_AUTORCC")) {
+ // Register qrc file
+ {
+ 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, qrc.Options);
+ }
+ }
+ this->Qrcs.push_back(std::move(qrc));
+ }
+ }
+ }
+ // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
+ // 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.
+ this->Target->ClearSourcesCache();
+ }
+ // Read skip files from makefile sources
+ if (this->MocEnabled || this->UicEnabled) {
+ std::string pathError;
+ for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ // Since we're iterating over source files that might be not in the
+ // target we need to check for path errors (not existing files).
+ std::string const& fPath = sf->GetFullPath(&pathError);
+ if (!pathError.empty()) {
+ pathError.clear();
+ continue;
+ }
+ 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
+ if (!generatedSources.empty() || !generatedHeaders.empty()) {
+ // Check status of policy CMP0071
+ bool policyAccept = false;
+ bool policyWarn = false;
+ cmPolicies::PolicyStatus const CMP0071_status =
+ makefile->GetPolicyStatus(cmPolicies::CMP0071);
+ switch (CMP0071_status) {
+ case cmPolicies::WARN:
+ policyWarn = true;
+ CM_FALLTHROUGH;
+ case cmPolicies::OLD:
+ // Ignore GENERATED file
+ break;
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::NEW:
+ // Process GENERATED file
+ policyAccept = true;
+ break;
+ }
+
+ if (policyAccept) {
+ // Accept GENERATED sources
+ for (std::string const& absFile : generatedHeaders) {
+ this->Headers.push_back(absFile);
+ autogenDependFiles.insert(absFile);
+ }
+ for (std::string const& absFile : generatedSources) {
+ this->Sources.push_back(absFile);
+ autogenDependFiles.insert(absFile);
+ }
+ } else {
+ if (policyWarn) {
+ std::string msg;
+ msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
+ msg += "\n";
+ std::string tools;
+ std::string property;
+ if (this->MocEnabled && this->UicEnabled) {
+ tools = "AUTOMOC and AUTOUIC";
+ property = "SKIP_AUTOGEN";
+ } else if (this->MocEnabled) {
+ tools = "AUTOMOC";
+ property = "SKIP_AUTOMOC";
+ } else if (this->UicEnabled) {
+ tools = "AUTOUIC";
+ property = "SKIP_AUTOUIC";
+ }
+ msg += "For compatibility, CMake is excluding the GENERATED source "
+ "file(s):\n";
+ for (const std::string& absFile : generatedHeaders) {
+ msg.append(" ").append(Quoted(absFile)).append("\n");
+ }
+ for (const std::string& absFile : generatedSources) {
+ msg.append(" ").append(Quoted(absFile)).append("\n");
+ }
+ msg += "from processing by ";
+ msg += tools;
+ msg +=
+ ". If any of the files should be processed, set CMP0071 to NEW. "
+ "If any of the files should not be processed, "
+ "explicitly exclude them by setting the source file property ";
+ msg += property;
+ msg += ":\n set_property(SOURCE file.h PROPERTY ";
+ msg += property;
+ msg += " ON)\n";
+ makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
+ }
+ }
+ // Clear lists
+ generatedSources.clear();
+ generatedHeaders.clear();
+ }
+ // Sort headers and sources
+ 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 (!this->Qrcs.empty()) {
+ const bool QtV5 = (this->QtVersionMajor == "5");
+ // Target rcc options
+ std::vector<std::string> optionsTarget;
+ cmSystemTools::ExpandListArgument(
+ GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget);
+
+ // Check if file name is unique
+ 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 and file names
+ {
+ cmFilePathChecksum const fpathCheckSum(makefile);
+ for (Qrc& qrc : this->Qrcs) {
+ qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile);
+ // RCC output file name
+ {
+ 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.txt";
+ }
+ }
+ }
+ // RCC options
+ for (Qrc& qrc : this->Qrcs) {
+ // Target options
+ std::vector<std::string> opts = optionsTarget;
+ // Merge computed "-name XYZ" option
+ {
+ std::string name = qrc.QrcName;
+ // Replace '-' with '_'. The former is not valid for symbol names.
+ std::replace(name.begin(), name.end(), '-', '_');
+ if (!qrc.Unique) {
+ name += "_";
+ name += qrc.PathChecksum;
+ }
+ std::vector<std::string> nameOpts;
+ nameOpts.emplace_back("-name");
+ nameOpts.emplace_back(std::move(name));
+ RccMergeOptions(opts, nameOpts, QtV5);
+ }
+ // Merge file option
+ RccMergeOptions(opts, qrc.Options, QtV5);
+ qrc.Options = std::move(opts);
+ }
+ for (Qrc& qrc : this->Qrcs) {
+ // Register file at target
+ this->AddGeneratedSource(qrc.RccFile, GeneratorT::RCC);
+
+ std::vector<std::string> ccOutput;
+ ccOutput.push_back(qrc.RccFile);
+ cmCustomCommandLines commandLines;
+ {
+ 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));
+ }
+ 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 and info file to the custom target dependencies
+ ccDepends.push_back(qrc.QrcFile);
+ ccDepends.push_back(qrc.InfoFile);
+
+ cmTarget* autoRccTarget = makefile->AddUtilityCommand(
+ ccName, cmMakefile::TargetOrigin::Generator, 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 {
+ // Create custom rcc command
+ {
+ std::vector<std::string> ccByproducts;
+ std::vector<std::string> ccDepends;
+ // Add the .qrc and info file to the custom command dependencies
+ ccDepends.push_back(qrc.QrcFile);
+ ccDepends.push_back(qrc.InfoFile);
+
+ // Add the resource files to the dependencies
+ {
+ std::string error;
+ if (RccListInputs(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());
+ }
+ }
+ makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends,
+ /*main_dependency*/ std::string(),
+ commandLines, ccComment.c_str(),
+ this->DirWork.c_str());
+ }
+ // Reconfigure when .qrc file changes
+ makefile->AddCMakeDependFile(qrc.QrcFile);
+ }
+ }
+ }
+
+ // 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);
+ }
+ }
+ }
+ }
+
+ // 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();
+ }
+
+ // 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));
+ }
+
+ // 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);
+ }
+
+ // 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
+ {
+ // add_dependencies/addUtility do not support generator expressions.
+ // We depend only on the libraries found in all configs therefore.
+ std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
+ 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)) {
+ // Increment target config count
+ commonTargets[libTarget]++;
+ }
+ }
+ }
+ }
+ for (auto const& item : commonTargets) {
+ if (item.second == this->ConfigsList.size()) {
+ autogenDependTargets.insert(item.first->Target);
+ }
+ }
+ }
+
+ // Create autogen target
+ cmTarget* autogenTarget = makefile->AddUtilityCommand(
+ this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true,
+ this->DirWork.c_str(), /*byproducts=*/autogenProvides,
+ std::vector<std::string>(autogenDependFiles.begin(),
+ autogenDependFiles.end()),
+ 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);
+ }
+ // Add additional autogen target dependencies to autogen target
+ for (cmTarget* depTarget : autogenDependTargets) {
+ autogenTarget->AddUtility(depTarget->GetName(), makefile);
+ }
+
+ // 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
+ this->Target->Target->AddUtility(this->AutogenTargetName, makefile);
+ }
+ }
+}
+
+void cmQtAutoGenInitializer::SetupCustomTargets()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Create info directory on demand
+ if (!cmSystemTools::MakeDirectory(this->DirInfo)) {
+ std::string emsg = ("Could not create directory: ");
+ emsg += Quoted(this->DirInfo);
+ cmSystemTools::Error(emsg.c_str());
+ }
+
+ // Configuration include directories
+ std::string includeDir = "include";
+ std::map<std::string, std::string> includeDirs;
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string& dir = includeDirs[cfg];
+ dir = "include_";
+ dir += cfg;
+ }
+
+ // Generate autogen target info file
+ if (this->MocEnabled || this->UicEnabled) {
+ if (this->MocEnabled) {
+ this->SetupCustomTargetsMoc();
+ }
+ if (this->UicEnabled) {
+ this->SetupCustomTargetsUic();
+ }
+
+ // Parallel processing
+ this->Parallel = GetSafeProperty(this->Target, "AUTOGEN_PARALLEL");
+ if (this->Parallel.empty() || (this->Parallel == "AUTO")) {
+ // Autodetect number of CPUs
+ this->Parallel = std::to_string(GetParallelCPUCount());
+ }
+
+ cmGeneratedFileStream ofs;
+ ofs.SetCopyIfDifferent(true);
+ ofs.Open(this->AutogenInfoFile.c_str(), false, true);
+ if (ofs) {
+ // Utility lambdas
+ auto CWrite = [&ofs](const char* key, std::string const& value) {
+ ofs << "set(" << key << " " << cmOutputConverter::EscapeForCMake(value)
+ << ")\n";
+ };
+ auto CWriteList = [&CWrite](const char* key,
+ std::vector<std::string> const& list) {
+ CWrite(key, cmJoin(list, ";"));
+ };
+ auto CWriteNestedLists = [&CWrite](
+ const char* key, std::vector<std::vector<std::string>> const& lists) {
+ std::vector<std::string> seplist;
+ for (const std::vector<std::string>& list : lists) {
+ std::string blist = "{";
+ blist += cmJoin(list, ";");
+ blist += "}";
+ seplist.push_back(std::move(blist));
+ }
+ CWrite(key, cmJoin(seplist, cmQtAutoGen::ListSep));
+ };
+ auto CWriteSet = [&CWrite](const char* key,
+ std::set<std::string> const& list) {
+ CWrite(key, cmJoin(list, ";"));
+ };
+ auto CWriteMap = [&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";
+ }
+ };
+ auto MfDef = [makefile](const char* key) {
+ return std::string(makefile->GetSafeDefinition(key));
+ };
+
+ // Write
+ ofs << "# Meta\n";
+ CWrite("AM_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+ CWrite("AM_PARALLEL", this->Parallel);
+
+ ofs << "# Directories\n";
+ CWrite("AM_CMAKE_SOURCE_DIR", MfDef("CMAKE_SOURCE_DIR"));
+ CWrite("AM_CMAKE_BINARY_DIR", MfDef("CMAKE_BINARY_DIR"));
+ CWrite("AM_CMAKE_CURRENT_SOURCE_DIR", MfDef("CMAKE_CURRENT_SOURCE_DIR"));
+ CWrite("AM_CMAKE_CURRENT_BINARY_DIR", MfDef("CMAKE_CURRENT_BINARY_DIR"));
+ CWrite("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE",
+ MfDef("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"));
+ CWrite("AM_BUILD_DIR", this->DirBuild);
+ if (this->MultiConfig) {
+ CWriteMap("AM_INCLUDE_DIR", includeDirs);
+ } else {
+ CWrite("AM_INCLUDE_DIR", includeDir);
+ }
+
+ ofs << "# Files\n";
+ CWriteList("AM_SOURCES", this->Sources);
+ CWriteList("AM_HEADERS", this->Headers);
+ if (this->MultiConfig) {
+ std::map<std::string, std::string> settingsFiles;
+ for (std::string const& cfg : this->ConfigsList) {
+ settingsFiles[cfg] =
+ AppendFilenameSuffix(this->AutogenSettingsFile, "_" + cfg);
+ }
+ CWriteMap("AM_SETTINGS_FILE", settingsFiles);
+ } else {
+ CWrite("AM_SETTINGS_FILE", this->AutogenSettingsFile);
+ }
+
+ ofs << "# Qt\n";
+ CWrite("AM_QT_VERSION_MAJOR", this->QtVersionMajor);
+ CWrite("AM_QT_MOC_EXECUTABLE", this->MocExecutable);
+ CWrite("AM_QT_UIC_EXECUTABLE", this->UicExecutable);
+
+ if (this->MocEnabled) {
+ ofs << "# MOC settings\n";
+ CWriteSet("AM_MOC_SKIP", this->MocSkip);
+ CWrite("AM_MOC_DEFINITIONS", this->MocDefines);
+ CWriteMap("AM_MOC_DEFINITIONS", this->MocDefinesConfig);
+ CWrite("AM_MOC_INCLUDES", this->MocIncludes);
+ CWriteMap("AM_MOC_INCLUDES", this->MocIncludesConfig);
+ CWrite("AM_MOC_OPTIONS",
+ GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS"));
+ CWrite("AM_MOC_RELAXED_MODE", MfDef("CMAKE_AUTOMOC_RELAXED_MODE"));
+ CWrite("AM_MOC_MACRO_NAMES",
+ GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES"));
+ CWrite("AM_MOC_DEPEND_FILTERS",
+ GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS"));
+ CWrite("AM_MOC_PREDEFS_CMD", this->MocPredefsCmd);
+ }
+
+ if (this->UicEnabled) {
+ ofs << "# UIC settings\n";
+ CWriteSet("AM_UIC_SKIP", this->UicSkip);
+ CWrite("AM_UIC_TARGET_OPTIONS", this->UicOptions);
+ CWriteMap("AM_UIC_TARGET_OPTIONS", this->UicOptionsConfig);
+ CWriteList("AM_UIC_OPTIONS_FILES", this->UicFileFiles);
+ CWriteNestedLists("AM_UIC_OPTIONS_OPTIONS", this->UicFileOptions);
+ CWriteList("AM_UIC_SEARCH_PATHS", this->UicSearchPaths);
+ }
+ } else {
+ return;
+ }
+ }
+
+ // Generate auto RCC info files
+ if (this->RccEnabled) {
+ for (Qrc const& qrc : this->Qrcs) {
+ cmGeneratedFileStream ofs;
+ ofs.SetCopyIfDifferent(true);
+ ofs.Open(qrc.InfoFile.c_str(), false, true);
+ if (ofs) {
+ // Utility lambdas
+ auto CWrite = [&ofs](const char* key, std::string const& value) {
+ ofs << "set(" << key << " "
+ << cmOutputConverter::EscapeForCMake(value) << ")\n";
+ };
+ auto CWriteMap = [&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";
+ }
+ };
+
+ // Write
+ ofs << "# Configurations\n";
+ CWrite("ARCC_MULTI_CONFIG", this->MultiConfig ? "TRUE" : "FALSE");
+
+ ofs << "# Settings file\n";
+ if (this->MultiConfig) {
+ std::map<std::string, std::string> settingsFiles;
+ for (std::string const& cfg : this->ConfigsList) {
+ settingsFiles[cfg] =
+ AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg);
+ }
+ CWriteMap("ARCC_SETTINGS_FILE", settingsFiles);
+ } else {
+ CWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile);
+ }
+
+ ofs << "# Directories\n";
+ CWrite("ARCC_BUILD_DIR", this->DirBuild);
+ if (this->MultiConfig) {
+ CWriteMap("ARCC_INCLUDE_DIR", includeDirs);
+ } else {
+ CWrite("ARCC_INCLUDE_DIR", includeDir);
+ }
+
+ ofs << "# Rcc executable\n";
+ CWrite("ARCC_RCC_EXECUTABLE", this->RccExecutable);
+ CWrite("ARCC_RCC_LIST_OPTIONS", cmJoin(this->RccListOptions, ";"));
+
+ ofs << "# Rcc job\n";
+ CWrite("ARCC_SOURCE", qrc.QrcFile);
+ CWrite("ARCC_OUTPUT_CHECKSUM", qrc.PathChecksum);
+ CWrite("ARCC_OUTPUT_NAME",
+ cmSystemTools::GetFilenameName(qrc.RccFile));
+ CWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";"));
+ CWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";"));
+ } else {
+ return;
+ }
+ }
+ }
+}
+
+void cmQtAutoGenInitializer::SetupCustomTargetsMoc()
+{
+ cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Moc predefs command
+ if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
+ this->QtVersionGreaterOrEqual(5, 8)) {
+ this->MocPredefsCmd =
+ 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
+ this->MocIncludes = GetIncludeDirs(this->ConfigDefault);
+ this->MocDefines = GetCompileDefinitions(this->ConfigDefault);
+ // Other configuration settings
+ for (std::string const& cfg : this->ConfigsList) {
+ {
+ std::string const configIncludeDirs = GetIncludeDirs(cfg);
+ if (configIncludeDirs != this->MocIncludes) {
+ this->MocIncludesConfig[cfg] = configIncludeDirs;
+ }
+ }
+ {
+ std::string const configCompileDefs = GetCompileDefinitions(cfg);
+ if (configCompileDefs != this->MocDefines) {
+ this->MocDefinesConfig[cfg] = configCompileDefs;
+ }
+ }
+ }
+ }
+
+ // 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 {
+ err = "The AUTOMOC feature supports only Qt 4 and Qt 5";
+ }
+
+ if (err.empty()) {
+ this->MocExecutable = mocExec;
+ } else {
+ err += " (";
+ err += this->Target->GetName();
+ err += ")";
+ cmSystemTools::Error(err.c_str());
+ }
+ }
+}
+
+void cmQtAutoGenInitializer::SetupCustomTargetsUic()
+{
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+
+ // Uic search paths
+ {
+ std::string const usp =
+ GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS");
+ if (!usp.empty()) {
+ cmSystemTools::ExpandListArgument(usp, this->UicSearchPaths);
+ std::string const srcDir = makefile->GetCurrentSourceDirectory();
+ for (std::string& path : this->UicSearchPaths) {
+ path = cmSystemTools::CollapseFullPath(path, srcDir);
+ }
+ }
+ }
+ // 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
+ this->UicOptions = UicGetOpts(this->ConfigDefault);
+
+ // Configuration specific settings
+ for (std::string const& cfg : this->ConfigsList) {
+ std::string const configUicOpts = UicGetOpts(cfg);
+ if (configUicOpts != this->UicOptions) {
+ this->UicOptionsConfig[cfg] = configUicOpts;
+ }
+ }
+ }
+ // .ui files skip and options
+ {
+ std::string const uiExt = "ui";
+ std::string pathError;
+ for (cmSourceFile* sf : makefile->GetSourceFiles()) {
+ // sf->GetExtension() is only valid after sf->GetFullPath() ...
+ // Since we're iterating over source files that might be not in the
+ // target we need to check for path errors (not existing files).
+ std::string const& fPath = sf->GetFullPath(&pathError);
+ if (!pathError.empty()) {
+ pathError.clear();
+ continue;
+ }
+ 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) {
+ this->UicFileFiles.push_back(absFile);
+ std::vector<std::string> optsVec;
+ cmSystemTools::ExpandListArgument(uicOpts, optsVec);
+ this->UicFileOptions.push_back(std::move(optsVec));
+ }
+ }
+ }
+ }
+ }
+
+ // 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()) {
+ this->UicExecutable = uicExec;
+ } else {
+ err += " (";
+ err += this->Target->GetName();
+ err += ")";
+ cmSystemTools::Error(err.c_str());
+ }
+ }
+}
+
+void cmQtAutoGenInitializer::AddGeneratedSource(std::string const& filename,
+ GeneratorT genType)
+{
+ // Register source file in makefile
+ cmMakefile* makefile = this->Target->Target->GetMakefile();
+ {
+ cmSourceFile* gFile = makefile->GetOrCreateSource(filename, true);
+ gFile->SetProperty("GENERATED", "1");
+ gFile->SetProperty("SKIP_AUTOGEN", "On");
+ }
+
+ // Add source file to source group
+ AddToSourceGroup(makefile, filename, genType);
+
+ // Add source file to target
+ this->Target->AddSource(filename);
+}
+
+std::string cmQtAutoGenInitializer::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 cmQtAutoGenInitializer::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 cmQtAutoGenInitializer::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;
+}
+
+/// @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 read
+bool cmQtAutoGenInitializer::RccListInputs(std::string const& fileName,
+ std::vector<std::string>& files,
+ std::string& error)
+{
+ if (!cmSystemTools::FileExists(fileName)) {
+ error = "rcc resource file does not exist:\n ";
+ error += Quoted(fileName);
+ error += "\n";
+ return false;
+ }
+ if (!RccListOptions.empty()) {
+ // Use rcc for file listing
+ if (RccExecutable.empty()) {
+ error = "rcc executable not available";
+ return false;
+ }
+
+ // Run rcc list command in the directory of the qrc file with the
+ // pathless
+ // qrc file name argument. This way rcc prints relative paths.
+ // This avoids issues on Windows when the qrc file is in a path that
+ // contains non-ASCII characters.
+ std::string const fileDir = cmSystemTools::GetFilenamePath(fileName);
+ std::string const fileNameName = cmSystemTools::GetFilenameName(fileName);
+
+ bool result = false;
+ int retVal = 0;
+ std::string rccStdOut;
+ std::string rccStdErr;
+ {
+ std::vector<std::string> cmd;
+ cmd.push_back(RccExecutable);
+ cmd.insert(cmd.end(), RccListOptions.begin(), RccListOptions.end());
+ cmd.push_back(fileNameName);
+ result = cmSystemTools::RunSingleCommand(
+ cmd, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(),
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
+ }
+ if (!result || retVal) {
+ error = "rcc list process failed for:\n ";
+ error += Quoted(fileName);
+ error += "\n";
+ error += rccStdOut;
+ error += "\n";
+ error += rccStdErr;
+ error += "\n";
+ return false;
+ }
+ if (!RccListParseOutput(rccStdOut, rccStdErr, files, error)) {
+ return false;
+ }
+ } else {
+ // We can't use rcc for the file listing.
+ // Read the qrc file content into string and parse it.
+ {
+ std::string qrcContents;
+ {
+ cmsys::ifstream ifs(fileName.c_str());
+ if (ifs) {
+ std::ostringstream osst;
+ osst << ifs.rdbuf();
+ qrcContents = osst.str();
+ } else {
+ error = "rcc file not readable:\n ";
+ error += Quoted(fileName);
+ error += "\n";
+ return false;
+ }
+ }
+ // Parse string content
+ RccListParseContent(qrcContents, files);
+ }
+ }
+
+ // Convert relative paths to absolute paths
+ RccListConvertFullPath(cmSystemTools::GetFilenamePath(fileName), files);
+ return true;
+}
diff --git a/Source/cmQtAutoGenInitializer.h b/Source/cmQtAutoGenInitializer.h
new file mode 100644
index 000000000..2a47e46a4
--- /dev/null
+++ b/Source/cmQtAutoGenInitializer.h
@@ -0,0 +1,115 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGenInitializer_h
+#define cmQtAutoGenInitializer_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmQtAutoGen.h"
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+class cmGeneratorTarget;
+
+/// @brief Initializes the QtAutoGen generators
+class cmQtAutoGenInitializer : public cmQtAutoGen
+{
+public:
+ static std::string GetQtMajorVersion(cmGeneratorTarget const* target);
+ static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
+ std::string const& qtVersionMajor);
+
+ /// @brief Rcc job information
+ 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:
+ cmQtAutoGenInitializer(cmGeneratorTarget* target, bool mocEnabled,
+ bool uicEnabled, bool rccEnabled,
+ std::string const& qtVersionMajor);
+
+ void InitCustomTargets();
+ void SetupCustomTargets();
+
+private:
+ void SetupCustomTargetsMoc();
+ void SetupCustomTargetsUic();
+
+ void AddGeneratedSource(std::string const& filename, GeneratorT genType);
+
+ bool QtVersionGreaterOrEqual(unsigned long requestMajor,
+ unsigned long requestMinor) const;
+
+ bool RccListInputs(std::string const& fileName,
+ std::vector<std::string>& files,
+ std::string& errorMessage);
+
+private:
+ cmGeneratorTarget* Target;
+ bool MocEnabled;
+ bool UicEnabled;
+ bool RccEnabled;
+ bool MultiConfig;
+ // Qt
+ std::string QtVersionMajor;
+ std::string QtVersionMinor;
+ std::string MocExecutable;
+ std::string UicExecutable;
+ std::string RccExecutable;
+ std::vector<std::string> RccListOptions;
+ // Configurations
+ std::string ConfigDefault;
+ std::vector<std::string> ConfigsList;
+ std::string Parallel;
+ // 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;
+ // Moc
+ std::string MocPredefsCmd;
+ std::set<std::string> MocSkip;
+ std::string MocIncludes;
+ std::map<std::string, std::string> MocIncludesConfig;
+ std::string MocDefines;
+ std::map<std::string, std::string> MocDefinesConfig;
+ // Uic
+ std::set<std::string> UicSkip;
+ std::vector<std::string> UicSearchPaths;
+ std::string UicOptions;
+ std::map<std::string, std::string> UicOptionsConfig;
+ std::vector<std::string> UicFileFiles;
+ std::vector<std::vector<std::string>> UicFileOptions;
+ // Rcc
+ std::vector<Qrc> Qrcs;
+};
+
+#endif
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
new file mode 100644
index 000000000..1939bd4e6
--- /dev/null
+++ b/Source/cmQtAutoGenerator.cxx
@@ -0,0 +1,641 @@
+/* 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 "cmAlgorithms.h"
+#include "cmGlobalGenerator.h"
+#include "cmMakefile.h"
+#include "cmStateDirectory.h"
+#include "cmStateSnapshot.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#include <algorithm>
+
+// -- Class methods
+
+void cmQtAutoGenerator::Logger::SetVerbose(bool value)
+{
+ Verbose_ = value;
+}
+
+void cmQtAutoGenerator::Logger::SetColorOutput(bool value)
+{
+ ColorOutput_ = value;
+}
+
+std::string cmQtAutoGenerator::Logger::HeadLine(std::string const& title)
+{
+ std::string head = title;
+ head += '\n';
+ head.append(head.size() - 1, '-');
+ head += '\n';
+ return head;
+}
+
+void cmQtAutoGenerator::Logger::Info(GeneratorT genType,
+ std::string const& message)
+{
+ std::string msg = GeneratorName(genType);
+ msg += ": ";
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
+ }
+}
+
+void cmQtAutoGenerator::Logger::Warning(GeneratorT genType,
+ std::string const& message)
+{
+ std::string msg;
+ if (message.find('\n') == std::string::npos) {
+ // Single line message
+ msg += GeneratorName(genType);
+ msg += " warning: ";
+ } else {
+ // Multi line message
+ msg += HeadLine(GeneratorName(genType) + " warning");
+ }
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stdout(msg.c_str(), msg.size());
+ }
+}
+
+void cmQtAutoGenerator::Logger::WarningFile(GeneratorT genType,
+ std::string const& filename,
+ std::string const& message)
+{
+ std::string msg = " ";
+ msg += Quoted(filename);
+ msg.push_back('\n');
+ // Message
+ msg += message;
+ Warning(genType, msg);
+}
+
+void cmQtAutoGenerator::Logger::Error(GeneratorT genType,
+ std::string const& message)
+{
+ std::string msg;
+ msg += HeadLine(GeneratorName(genType) + " error");
+ // Message
+ msg += message;
+ if (msg.back() != '\n') {
+ msg.push_back('\n');
+ }
+ msg.push_back('\n');
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
+ }
+}
+
+void cmQtAutoGenerator::Logger::ErrorFile(GeneratorT genType,
+ std::string const& filename,
+ std::string const& message)
+{
+ std::string emsg = " ";
+ emsg += Quoted(filename);
+ emsg += '\n';
+ // Message
+ emsg += message;
+ Error(genType, emsg);
+}
+
+void cmQtAutoGenerator::Logger::ErrorCommand(
+ GeneratorT genType, std::string const& message,
+ std::vector<std::string> const& command, std::string const& output)
+{
+ std::string msg;
+ msg.push_back('\n');
+ msg += HeadLine(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');
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ cmSystemTools::Stderr(msg.c_str(), msg.size());
+ }
+}
+
+std::string cmQtAutoGenerator::FileSystem::RealPath(
+ std::string const& filename)
+{
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmSystemTools::GetRealPath(filename);
+}
+
+bool cmQtAutoGenerator::FileSystem::FileExists(std::string const& filename)
+{
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmSystemTools::FileExists(filename);
+}
+
+bool cmQtAutoGenerator::FileSystem::FileIsOlderThan(
+ std::string const& buildFile, std::string const& sourceFile,
+ std::string* error)
+{
+ bool res(false);
+ int result = 0;
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ res = cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result);
+ }
+ if (res) {
+ res = (result < 0);
+ } else {
+ if (error != nullptr) {
+ error->append(
+ "File modification time comparison failed for the files\n ");
+ error->append(Quoted(buildFile));
+ error->append("\nand\n ");
+ error->append(Quoted(sourceFile));
+ }
+ }
+ return res;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileRead(std::string& content,
+ std::string const& filename,
+ std::string* error)
+{
+ bool success = false;
+ {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ if (cmSystemTools::FileExists(filename, true)) {
+ std::size_t const length = cmSystemTools::FileLength(filename);
+ cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary));
+ if (ifs) {
+ if (length > 0) {
+ 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 {
+ // Readable but empty file
+ content.clear();
+ success = true;
+ }
+ } else if (error != nullptr) {
+ error->append("Opening the file for reading failed.");
+ }
+ } else if (error != nullptr) {
+ error->append(
+ "The file does not exist, is not readable or is a directory.");
+ }
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileRead(GeneratorT genType,
+ std::string& content,
+ std::string const& filename)
+{
+ std::string error;
+ if (!FileRead(content, filename, &error)) {
+ Log()->ErrorFile(genType, filename, error);
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileWrite(std::string const& filename,
+ std::string const& content,
+ std::string* error)
+{
+ bool success = false;
+ // Make sure the parent directory exists
+ if (MakeParentDirectory(filename)) {
+ std::lock_guard<std::mutex> lock(Mutex_);
+ 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()) {
+ success = true;
+ } else {
+ if (error != nullptr) {
+ error->assign("File writing failed");
+ }
+ }
+ } else {
+ if (error != nullptr) {
+ error->assign("Opening file for writing failed");
+ }
+ }
+ } else {
+ if (error != nullptr) {
+ error->assign("Could not create parent directory");
+ }
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileWrite(GeneratorT genType,
+ std::string const& filename,
+ std::string const& content)
+{
+ std::string error;
+ if (!FileWrite(filename, content, &error)) {
+ Log()->ErrorFile(genType, filename, error);
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileDiffers(std::string const& filename,
+ std::string const& content)
+{
+ bool differs = true;
+ {
+ std::string oldContents;
+ if (FileRead(oldContents, filename)) {
+ differs = (oldContents != content);
+ }
+ }
+ return differs;
+}
+
+bool cmQtAutoGenerator::FileSystem::FileRemove(std::string const& filename)
+{
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmSystemTools::RemoveFile(filename);
+}
+
+bool cmQtAutoGenerator::FileSystem::Touch(std::string const& filename)
+{
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmSystemTools::Touch(filename, false);
+}
+
+bool cmQtAutoGenerator::FileSystem::MakeDirectory(std::string const& dirname)
+{
+ std::lock_guard<std::mutex> lock(Mutex_);
+ return cmSystemTools::MakeDirectory(dirname);
+}
+
+bool cmQtAutoGenerator::FileSystem::MakeDirectory(GeneratorT genType,
+ std::string const& dirname)
+{
+ if (!MakeDirectory(dirname)) {
+ Log()->ErrorFile(genType, dirname, "Could not create directory");
+ return false;
+ }
+ return true;
+}
+
+bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
+ std::string const& filename)
+{
+ bool success = true;
+ std::string const dirName = cmSystemTools::GetFilenamePath(filename);
+ if (!dirName.empty()) {
+ success = MakeDirectory(dirName);
+ }
+ return success;
+}
+
+bool cmQtAutoGenerator::FileSystem::MakeParentDirectory(
+ GeneratorT genType, std::string const& filename)
+{
+ if (!MakeParentDirectory(filename)) {
+ Log()->ErrorFile(genType, filename, "Could not create parent directory");
+ return false;
+ }
+ return true;
+}
+
+int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::init(uv_loop_t* uv_loop,
+ ReadOnlyProcessT* process)
+{
+ Process_ = process;
+ Target_ = nullptr;
+ return UVPipe_.init(*uv_loop, 0, this);
+}
+
+int cmQtAutoGenerator::ReadOnlyProcessT::PipeT::startRead(std::string* target)
+{
+ Target_ = target;
+ return uv_read_start(uv_stream(), &PipeT::UVAlloc, &PipeT::UVData);
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::reset()
+{
+ Process_ = nullptr;
+ Target_ = nullptr;
+ UVPipe_.reset();
+ Buffer_.clear();
+ Buffer_.shrink_to_fit();
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVAlloc(uv_handle_t* handle,
+ size_t suggestedSize,
+ uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<PipeT*>(handle->data);
+ pipe.Buffer_.resize(suggestedSize);
+ buf->base = &pipe.Buffer_.front();
+ buf->len = pipe.Buffer_.size();
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::PipeT::UVData(uv_stream_t* stream,
+ ssize_t nread,
+ const uv_buf_t* buf)
+{
+ auto& pipe = *reinterpret_cast<PipeT*>(stream->data);
+ if (nread > 0) {
+ // Append data to merged output
+ if ((buf->base != nullptr) && (pipe.Target_ != nullptr)) {
+ pipe.Target_->append(buf->base, nread);
+ }
+ } else if (nread < 0) {
+ // EOF or error
+ auto* proc = pipe.Process_;
+ // Check it this an unusual error
+ if (nread != UV_EOF) {
+ if (!proc->Result()->error()) {
+ proc->Result()->ErrorMessage =
+ "libuv reading from pipe failed with error code ";
+ proc->Result()->ErrorMessage += std::to_string(nread);
+ }
+ }
+ // Clear libuv pipe handle and try to finish
+ pipe.reset();
+ proc->UVTryFinish();
+ }
+}
+
+void cmQtAutoGenerator::ProcessResultT::reset()
+{
+ ExitStatus = 0;
+ TermSignal = 0;
+ if (!StdOut.empty()) {
+ StdOut.clear();
+ StdOut.shrink_to_fit();
+ }
+ if (!StdErr.empty()) {
+ StdErr.clear();
+ StdErr.shrink_to_fit();
+ }
+ if (!ErrorMessage.empty()) {
+ ErrorMessage.clear();
+ ErrorMessage.shrink_to_fit();
+ }
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::setup(
+ ProcessResultT* result, bool mergedOutput,
+ std::vector<std::string> const& command, std::string const& workingDirectory)
+{
+ Setup_.WorkingDirectory = workingDirectory;
+ Setup_.Command = command;
+ Setup_.Result = result;
+ Setup_.MergedOutput = mergedOutput;
+}
+
+bool cmQtAutoGenerator::ReadOnlyProcessT::start(
+ uv_loop_t* uv_loop, std::function<void()>&& finishedCallback)
+{
+ if (IsStarted() || (Result() == nullptr)) {
+ return false;
+ }
+
+ // Reset result before the start
+ Result()->reset();
+
+ // Fill command string pointers
+ if (!Setup().Command.empty()) {
+ CommandPtr_.reserve(Setup().Command.size() + 1);
+ for (std::string const& arg : Setup().Command) {
+ CommandPtr_.push_back(arg.c_str());
+ }
+ CommandPtr_.push_back(nullptr);
+ } else {
+ Result()->ErrorMessage = "Empty command";
+ }
+
+ if (!Result()->error()) {
+ if (UVPipeOut_.init(uv_loop, this) != 0) {
+ Result()->ErrorMessage = "libuv stdout pipe initialization failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (UVPipeErr_.init(uv_loop, this) != 0) {
+ Result()->ErrorMessage = "libuv stderr pipe initialization failed";
+ }
+ }
+ if (!Result()->error()) {
+ // -- Setup process stdio options
+ // stdin
+ UVOptionsStdIO_[0].flags = UV_IGNORE;
+ UVOptionsStdIO_[0].data.stream = nullptr;
+ // stdout
+ UVOptionsStdIO_[1].flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ UVOptionsStdIO_[1].data.stream = UVPipeOut_.uv_stream();
+ // stderr
+ UVOptionsStdIO_[2].flags =
+ static_cast<uv_stdio_flags>(UV_CREATE_PIPE | UV_WRITABLE_PIPE);
+ UVOptionsStdIO_[2].data.stream = UVPipeErr_.uv_stream();
+
+ // -- Setup process options
+ std::fill_n(reinterpret_cast<char*>(&UVOptions_), sizeof(UVOptions_), 0);
+ UVOptions_.exit_cb = &ReadOnlyProcessT::UVExit;
+ UVOptions_.file = CommandPtr_[0];
+ UVOptions_.args = const_cast<char**>(&CommandPtr_.front());
+ UVOptions_.cwd = Setup_.WorkingDirectory.c_str();
+ UVOptions_.flags = UV_PROCESS_WINDOWS_HIDE;
+ UVOptions_.stdio_count = static_cast<int>(UVOptionsStdIO_.size());
+ UVOptions_.stdio = &UVOptionsStdIO_.front();
+
+ // -- Spawn process
+ if (UVProcess_.spawn(*uv_loop, UVOptions_, this) != 0) {
+ Result()->ErrorMessage = "libuv process spawn failed";
+ }
+ }
+ // -- Start reading from stdio streams
+ if (!Result()->error()) {
+ if (UVPipeOut_.startRead(&Result()->StdOut) != 0) {
+ Result()->ErrorMessage = "libuv start reading from stdout pipe failed";
+ }
+ }
+ if (!Result()->error()) {
+ if (UVPipeErr_.startRead(Setup_.MergedOutput ? &Result()->StdOut
+ : &Result()->StdErr) != 0) {
+ Result()->ErrorMessage = "libuv start reading from stderr pipe failed";
+ }
+ }
+
+ if (!Result()->error()) {
+ IsStarted_ = true;
+ FinishedCallback_ = std::move(finishedCallback);
+ } else {
+ // Clear libuv handles and finish
+ UVProcess_.reset();
+ UVPipeOut_.reset();
+ UVPipeErr_.reset();
+ CommandPtr_.clear();
+ }
+
+ return IsStarted();
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::UVExit(uv_process_t* handle,
+ int64_t exitStatus,
+ int termSignal)
+{
+ auto& proc = *reinterpret_cast<ReadOnlyProcessT*>(handle->data);
+ if (proc.IsStarted() && !proc.IsFinished()) {
+ // Set error message on demand
+ proc.Result()->ExitStatus = exitStatus;
+ proc.Result()->TermSignal = termSignal;
+ if (!proc.Result()->error()) {
+ if (termSignal != 0) {
+ proc.Result()->ErrorMessage = "Process was terminated by signal ";
+ proc.Result()->ErrorMessage +=
+ std::to_string(proc.Result()->TermSignal);
+ } else if (exitStatus != 0) {
+ proc.Result()->ErrorMessage = "Process failed with return value ";
+ proc.Result()->ErrorMessage +=
+ std::to_string(proc.Result()->ExitStatus);
+ }
+ }
+
+ // Reset process handle and try to finish
+ proc.UVProcess_.reset();
+ proc.UVTryFinish();
+ }
+}
+
+void cmQtAutoGenerator::ReadOnlyProcessT::UVTryFinish()
+{
+ // There still might be data in the pipes after the process has finished.
+ // Therefore check if the process is finished AND all pipes are closed
+ // before signaling the worker thread to continue.
+ if (UVProcess_.get() == nullptr) {
+ if (UVPipeOut_.uv_pipe() == nullptr) {
+ if (UVPipeErr_.uv_pipe() == nullptr) {
+ IsFinished_ = true;
+ FinishedCallback_();
+ }
+ }
+ }
+}
+
+cmQtAutoGenerator::cmQtAutoGenerator()
+ : FileSys_(&Logger_)
+{
+ // Initialize logger
+ Logger_.SetVerbose(cmSystemTools::HasEnv("VERBOSE"));
+ {
+ std::string colorEnv;
+ cmSystemTools::GetEnv("COLOR", colorEnv);
+ if (!colorEnv.empty()) {
+ Logger_.SetColorOutput(cmSystemTools::IsOn(colorEnv.c_str()));
+ } else {
+ Logger_.SetColorOutput(true);
+ }
+ }
+
+ // Initialize libuv loop
+ uv_disable_stdio_inheritance();
+#ifdef CMAKE_UV_SIGNAL_HACK
+ UVHackRAII_ = cm::make_unique<cmUVSignalHackRAII>();
+#endif
+ UVLoop_ = cm::make_unique<uv_loop_t>();
+ uv_loop_init(UVLoop());
+}
+
+cmQtAutoGenerator::~cmQtAutoGenerator()
+{
+ // Close libuv loop
+ uv_loop_close(UVLoop());
+}
+
+bool cmQtAutoGenerator::Run(std::string const& infoFile,
+ std::string const& config)
+{
+ // Info settings
+ InfoFile_ = infoFile;
+ cmSystemTools::ConvertToUnixSlashes(InfoFile_);
+ InfoDir_ = cmSystemTools::GetFilenamePath(infoFile);
+ InfoConfig_ = config;
+
+ bool success = false;
+ {
+ cmake cm(cmake::RoleScript);
+ cm.SetHomeOutputDirectory(InfoDir());
+ cm.SetHomeDirectory(InfoDir());
+ cm.GetCurrentSnapshot().SetDefaultDefinitions();
+ cmGlobalGenerator gg(&cm);
+
+ cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
+ snapshot.GetDirectory().SetCurrentBinary(InfoDir());
+ snapshot.GetDirectory().SetCurrentSource(InfoDir());
+
+ auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot);
+ // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
+ // https://gitlab.kitware.com/cmake/cmake/issues/17570
+ makefile->SetPolicyVersion("3.9");
+ gg.SetCurrentMakefile(makefile.get());
+ success = this->Init(makefile.get());
+ }
+ if (success) {
+ success = this->Process();
+ }
+ return success;
+}
+
+std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
+ const char* key)
+{
+ std::string prefix(key);
+ prefix += ':';
+ std::string::size_type pos = content.find(prefix);
+ if (pos != std::string::npos) {
+ pos += prefix.size();
+ if (pos < content.size()) {
+ std::string::size_type posE = content.find('\n', pos);
+ if ((posE != std::string::npos) && (posE != pos)) {
+ return content.substr(pos, posE - pos);
+ }
+ }
+ }
+ return std::string();
+}
diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h
new file mode 100644
index 000000000..e029d8d6b
--- /dev/null
+++ b/Source/cmQtAutoGenerator.h
@@ -0,0 +1,252 @@
+/* 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 "cmUVHandlePtr.h"
+#include "cmUVSignalHackRAII.h" // IWYU pragma: keep
+#include "cm_uv.h"
+
+#include <array>
+#include <functional>
+#include <mutex>
+#include <stddef.h>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+/// @brief Base class for QtAutoGen gernerators
+class cmQtAutoGenerator : public cmQtAutoGen
+{
+ CM_DISABLE_COPY(cmQtAutoGenerator)
+public:
+ // -- Types
+
+ /// @brief Thread safe logging
+ class Logger
+ {
+ public:
+ // -- Verbosity
+ bool Verbose() const { return this->Verbose_; }
+ void SetVerbose(bool value);
+ bool ColorOutput() const { return this->ColorOutput_; }
+ void SetColorOutput(bool value);
+ // -- Log info
+ void Info(GeneratorT genType, std::string const& message);
+ // -- Log warning
+ void Warning(GeneratorT genType, std::string const& message);
+ void WarningFile(GeneratorT genType, std::string const& filename,
+ std::string const& message);
+ // -- Log error
+ void Error(GeneratorT genType, std::string const& message);
+ void ErrorFile(GeneratorT genType, std::string const& filename,
+ std::string const& message);
+ void ErrorCommand(GeneratorT genType, std::string const& message,
+ std::vector<std::string> const& command,
+ std::string const& output);
+
+ private:
+ static std::string HeadLine(std::string const& title);
+
+ private:
+ std::mutex Mutex_;
+ bool volatile Verbose_ = false;
+ bool volatile ColorOutput_ = false;
+ };
+
+ /// @brief Thread safe file system interface
+ class FileSystem
+ {
+ public:
+ FileSystem(Logger* log)
+ : Log_(log)
+ {
+ }
+
+ Logger* Log() const { return Log_; }
+ std::string RealPath(std::string const& filename);
+ bool FileExists(std::string const& filename);
+ 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);
+ /// @brief Error logging version
+ bool FileRead(GeneratorT genType, std::string& content,
+ std::string const& filename);
+
+ bool FileWrite(std::string const& filename, std::string const& content,
+ std::string* error = nullptr);
+ /// @brief Error logging version
+ bool FileWrite(GeneratorT genType, std::string const& filename,
+ std::string const& content);
+
+ bool FileDiffers(std::string const& filename, std::string const& content);
+
+ bool FileRemove(std::string const& filename);
+ bool Touch(std::string const& filename);
+
+ bool MakeDirectory(std::string const& dirname);
+ /// @brief Error logging version
+ bool MakeDirectory(GeneratorT genType, std::string const& dirname);
+
+ bool MakeParentDirectory(std::string const& filename);
+ /// @brief Error logging version
+ bool MakeParentDirectory(GeneratorT genType, std::string const& filename);
+
+ private:
+ std::mutex Mutex_;
+ Logger* Log_;
+ };
+
+ /// @brief Return value and output of an external process
+ struct ProcessResultT
+ {
+ void reset();
+ bool error() const
+ {
+ return (ExitStatus != 0) || (TermSignal != 0) || !ErrorMessage.empty();
+ }
+
+ std::int64_t ExitStatus = 0;
+ int TermSignal = 0;
+ std::string StdOut;
+ std::string StdErr;
+ std::string ErrorMessage;
+ };
+
+ /// @brief External process management class
+ struct ReadOnlyProcessT
+ {
+ // -- Types
+
+ /// @brief libuv pipe buffer class
+ class PipeT
+ {
+ public:
+ int init(uv_loop_t* uv_loop, ReadOnlyProcessT* process);
+ int startRead(std::string* target);
+ void reset();
+
+ // -- Libuv casts
+ uv_pipe_t* uv_pipe() { return UVPipe_.get(); }
+ uv_stream_t* uv_stream()
+ {
+ return reinterpret_cast<uv_stream_t*>(uv_pipe());
+ }
+ uv_handle_t* uv_handle()
+ {
+ return reinterpret_cast<uv_handle_t*>(uv_pipe());
+ }
+
+ // -- Libuv callbacks
+ static void UVAlloc(uv_handle_t* handle, size_t suggestedSize,
+ uv_buf_t* buf);
+ static void UVData(uv_stream_t* stream, ssize_t nread,
+ const uv_buf_t* buf);
+
+ private:
+ ReadOnlyProcessT* Process_ = nullptr;
+ std::string* Target_ = nullptr;
+ std::vector<char> Buffer_;
+ cm::uv_pipe_ptr UVPipe_;
+ };
+
+ /// @brief Process settings
+ struct SetupT
+ {
+ std::string WorkingDirectory;
+ std::vector<std::string> Command;
+ ProcessResultT* Result = nullptr;
+ bool MergedOutput = false;
+ };
+
+ // -- Constructor
+ ReadOnlyProcessT() = default;
+
+ // -- Const accessors
+ const SetupT& Setup() const { return Setup_; }
+ ProcessResultT* Result() const { return Setup_.Result; }
+ bool IsStarted() const { return IsStarted_; }
+ bool IsFinished() const { return IsFinished_; }
+
+ // -- Runtime
+ void setup(ProcessResultT* result, bool mergedOutput,
+ std::vector<std::string> const& command,
+ std::string const& workingDirectory = std::string());
+ bool start(uv_loop_t* uv_loop, std::function<void()>&& finishedCallback);
+
+ private:
+ // -- Friends
+ friend class PipeT;
+ // -- Libuv callbacks
+ static void UVExit(uv_process_t* handle, int64_t exitStatus,
+ int termSignal);
+ void UVTryFinish();
+
+ // -- Setup
+ SetupT Setup_;
+ // -- Runtime
+ bool IsStarted_ = false;
+ bool IsFinished_ = false;
+ std::function<void()> FinishedCallback_;
+ std::vector<const char*> CommandPtr_;
+ std::array<uv_stdio_container_t, 3> UVOptionsStdIO_;
+ uv_process_options_t UVOptions_;
+ cm::uv_process_ptr UVProcess_;
+ PipeT UVPipeOut_;
+ PipeT UVPipeErr_;
+ };
+
+public:
+ // -- Constructors
+ cmQtAutoGenerator();
+ virtual ~cmQtAutoGenerator();
+
+ // -- Run
+ bool Run(std::string const& infoFile, std::string const& config);
+
+ // -- Accessors
+ // Logging
+ Logger& Log() { return Logger_; }
+ // File System
+ FileSystem& FileSys() { return FileSys_; }
+ // InfoFile
+ std::string const& InfoFile() const { return InfoFile_; }
+ std::string const& InfoDir() const { return InfoDir_; }
+ std::string const& InfoConfig() const { return InfoConfig_; }
+ // libuv loop
+ uv_loop_t* UVLoop() { return UVLoop_.get(); }
+ cm::uv_async_ptr& UVRequest() { return UVRequest_; }
+
+ // -- Utility
+ static std::string SettingsFind(std::string const& content, const char* key);
+
+protected:
+ // -- Abstract processing interface
+ virtual bool Init(cmMakefile* makefile) = 0;
+ virtual bool Process() = 0;
+
+private:
+ // -- Logging
+ Logger Logger_;
+ FileSystem FileSys_;
+ // -- Info settings
+ std::string InfoFile_;
+ std::string InfoDir_;
+ std::string InfoConfig_;
+// -- libuv loop
+#ifdef CMAKE_UV_SIGNAL_HACK
+ std::unique_ptr<cmUVSignalHackRAII> UVHackRAII_;
+#endif
+ std::unique_ptr<uv_loop_t> UVLoop_;
+ cm::uv_async_ptr UVRequest_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
deleted file mode 100644
index 89568c387..000000000
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ /dev/null
@@ -1,1236 +0,0 @@
-/* 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 "cmQtAutoGeneratorInitializer.h"
-
-#include "cmAlgorithms.h"
-#include "cmCustomCommand.h"
-#include "cmCustomCommandLines.h"
-#include "cmFilePathChecksum.h"
-#include "cmGeneratorTarget.h"
-#include "cmGlobalGenerator.h"
-#include "cmLinkItem.h"
-#include "cmLocalGenerator.h"
-#include "cmMakefile.h"
-#include "cmOutputConverter.h"
-#include "cmPolicies.h"
-#include "cmSourceFile.h"
-#include "cmSourceGroup.h"
-#include "cmState.h"
-#include "cmStateTypes.h"
-#include "cmSystemTools.h"
-#include "cmTarget.h"
-#include "cm_sys_stat.h"
-#include "cmake.h"
-#include "cmsys/FStream.hxx"
-
-#include <algorithm>
-#include <array>
-#include <deque>
-#include <map>
-#include <set>
-#include <sstream>
-#include <string>
-#include <utility>
-#include <vector>
-
-inline static const char* SafeString(const char* value)
-{
- return (value != nullptr) ? value : "";
-}
-
-inline static std::string GetSafeProperty(cmGeneratorTarget const* target,
- const char* key)
-{
- return std::string(SafeString(target->GetProperty(key)));
-}
-
-inline static std::string GetSafeProperty(cmSourceFile const* sf,
- const char* key)
-{
- 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)
-{
- makefile->AddDefinition(key,
- cmOutputConverter::EscapeForCMake(value).c_str());
-}
-
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
- const std::vector<std::string>& values)
-{
- makefile->AddDefinition(
- key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
-}
-
-static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
- const std::set<std::string>& values)
-{
- makefile->AddDefinition(
- key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
-}
-
-static void AddDefinitionEscaped(
- cmMakefile* makefile, const char* key,
- const std::vector<std::vector<std::string>>& lists)
-{
- std::vector<std::string> seplist;
- for (const std::vector<std::string>& list : lists) {
- std::string blist = "{";
- blist += cmJoin(list, ";");
- blist += "}";
- seplist.push_back(std::move(blist));
- }
- makefile->AddDefinition(key, cmOutputConverter::EscapeForCMake(
- cmJoin(seplist, cmQtAutoGen::listSep))
- .c_str());
-}
-
-static bool AddToSourceGroup(cmMakefile* makefile, std::string const& fileName,
- cmQtAutoGen::Generator genType)
-{
- cmSourceGroup* sourceGroup = nullptr;
- // Acquire source group
- {
- std::string property;
- std::string groupName;
- {
- std::array<std::string, 2> props;
- // Use generator specific group name
- switch (genType) {
- case cmQtAutoGen::MOC:
- props[0] = "AUTOMOC_SOURCE_GROUP";
- break;
- case cmQtAutoGen::RCC:
- props[0] = "AUTORCC_SOURCE_GROUP";
- break;
- default:
- props[0] = "AUTOGEN_SOURCE_GROUP";
- break;
- }
- props[1] = "AUTOGEN_SOURCE_GROUP";
- for (std::string& prop : props) {
- const char* propName = makefile->GetState()->GetGlobalProperty(prop);
- if ((propName != nullptr) && (*propName != '\0')) {
- groupName = propName;
- property = std::move(prop);
- break;
- }
- }
- }
- // Generate a source group on demand
- if (!groupName.empty()) {
- sourceGroup = makefile->GetOrCreateSourceGroup(groupName);
- if (sourceGroup == nullptr) {
- std::ostringstream ost;
- ost << cmQtAutoGen::GeneratorNameUpper(genType);
- ost << ": " << property;
- ost << ": Could not find or create the source group ";
- ost << cmQtAutoGen::Quoted(groupName);
- cmSystemTools::Error(ost.str().c_str());
- return false;
- }
- }
- }
- if (sourceGroup != nullptr) {
- sourceGroup->AddGroupFile(fileName);
- }
- return true;
-}
-
-static void AddCleanFile(cmMakefile* makefile, std::string const& fileName)
-{
- makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", fileName.c_str(),
- 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)
-{
- 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));
- }
- }
- {
- 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);
- }
- }
-
- return genFiles;
-}
-
-/* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its
- * recursive STATIC_LIBRARY dependencies depends on targetOrigin
- * (STATIC_LIBRARY cycle).
- */
-static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin,
- cmGeneratorTarget const* targetDepend,
- std::string const& config)
-{
- bool cycle = false;
- if ((targetOrigin->GetType() == cmStateEnums::STATIC_LIBRARY) &&
- (targetDepend->GetType() == cmStateEnums::STATIC_LIBRARY)) {
- std::set<cmGeneratorTarget const*> knownLibs;
- std::deque<cmGeneratorTarget const*> testLibs;
-
- // Insert initial static_library dependency
- knownLibs.insert(targetDepend);
- testLibs.push_back(targetDepend);
-
- while (!testLibs.empty()) {
- cmGeneratorTarget const* testTarget = testLibs.front();
- testLibs.pop_front();
- // Check if the test target is the origin target (cycle)
- if (testTarget == targetOrigin) {
- cycle = true;
- break;
- }
- // Collect all static_library dependencies from the test target
- cmLinkImplementationLibraries const* libs =
- testTarget->GetLinkImplementationLibraries(config);
- if (libs != nullptr) {
- for (cmLinkItem const& item : libs->Libraries) {
- cmGeneratorTarget const* depTarget = item.Target;
- if ((depTarget != nullptr) &&
- (depTarget->GetType() == cmStateEnums::STATIC_LIBRARY) &&
- knownLibs.insert(depTarget).second) {
- testLibs.push_back(depTarget);
- }
- }
- }
- }
- }
- 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)
-{
- // Read skip files from makefile sources
- {
- std::string pathError;
- for (cmSourceFile* sf : digest.Target->Makefile->GetSourceFiles()) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- // Since we're iterating over source files that might be not in the
- // target we need to check for path errors (not existing files).
- std::string const& fPath = sf->GetFullPath(&pathError);
- if (!pathError.empty()) {
- pathError.clear();
- continue;
- }
- 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);
- }
- }
- }
- }
-}
-
-static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest,
- std::string const& configDefault,
- std::vector<std::string> const& configsList,
- cmQtAutoGenSetup& setup)
-{
- 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, ";");
- };
-
- // 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);
- }
-
- // Moc executable
- {
- 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 (err.empty()) {
- AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec);
- } else {
- err += " (" + target->GetName() + ")";
- cmSystemTools::Error(err.c_str());
- }
- }
-}
-
-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();
-
- // Uic search paths
- {
- 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);
- }
- }
- }
- 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, ";");
- };
-
- // 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";
- std::string pathError;
- for (cmSourceFile* sf : makefile->GetSourceFiles()) {
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- // Since we're iterating over source files that might be not in the
- // target we need to check for path errors (not existing files).
- std::string const& fPath = sf->GetFullPath(&pathError);
- if (!pathError.empty()) {
- pathError.clear();
- continue;
- }
- 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);
- }
-
- AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip);
-
- // Uic executable
- {
- std::string err;
- std::string uicExec;
-
- 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());
- }
- }
-}
-
-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";
- }
- } 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";
- }
- } 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);
- // Remove old settings on cleanup
- {
- std::string base = autogenInfoDir + "/AutogenOldSettings";
- if (multiConfig == cmQtAutoGen::SINGLE) {
- AddCleanFile(makefile, base.append(".cmake"));
- } else {
- for (std::string const& cfg : configsList) {
- std::string filename = base;
- filename += "_";
- filename += cfg;
- filename += ".cmake";
- AddCleanFile(makefile, filename);
- }
- }
- }
-
- // 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);
- 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) {
- includeDir += "_$<CONFIG>";
- }
- target->AddIncludeDirectory(includeDir, true);
- }
-
- // Extract relevant source files
- std::vector<std::string> generatedSources;
- std::vector<std::string> generatedHeaders;
- {
- std::string const qrcExt = "qrc";
- std::vector<cmSourceFile*> srcFiles;
- target->GetConfigCommonSourceFiles(srcFiles);
- for (cmSourceFile* sf : srcFiles) {
- if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) {
- continue;
- }
- // sf->GetExtension() is only valid after sf->GetFullPath() ...
- 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) {
- 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"))) {
- // 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);
- }
- } else {
- if (generated) {
- generatedSources.push_back(absPath);
- } else {
- digest.Sources.push_back(absPath);
- }
- }
- }
- }
- }
- // Register rcc enabled files
- if (digest.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");
- // RCC options
- {
- std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS");
- if (!opts.empty()) {
- cmSystemTools::ExpandListArgument(opts, qrcDigest.Options);
- }
- }
- digest.Qrcs.push_back(std::move(qrcDigest));
- }
- }
- }
- // cmGeneratorTarget::GetConfigCommonSourceFiles computes the target's
- // 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();
- }
-
- // Process GENERATED sources and headers
- if (!generatedSources.empty() || !generatedHeaders.empty()) {
- // Check status of policy CMP0071
- bool policyAccept = false;
- bool policyWarn = false;
- cmPolicies::PolicyStatus const CMP0071_status =
- target->Makefile->GetPolicyStatus(cmPolicies::CMP0071);
- switch (CMP0071_status) {
- case cmPolicies::WARN:
- policyWarn = true;
- CM_FALLTHROUGH;
- case cmPolicies::OLD:
- // Ignore GENERATED file
- break;
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::NEW:
- // Process GENERATED file
- policyAccept = true;
- break;
- }
-
- if (policyAccept) {
- // Accept GENERATED sources
- for (std::string const& absFile : generatedHeaders) {
- digest.Headers.push_back(absFile);
- autogenDependFiles.insert(absFile);
- }
- for (std::string const& absFile : generatedSources) {
- digest.Sources.push_back(absFile);
- autogenDependFiles.insert(absFile);
- }
- } else {
- if (policyWarn) {
- std::string msg;
- msg += cmPolicies::GetPolicyWarning(cmPolicies::CMP0071);
- msg += "\n";
- std::string tools;
- std::string property;
- if (digest.MocEnabled && digest.UicEnabled) {
- tools = "AUTOMOC and AUTOUIC";
- property = "SKIP_AUTOGEN";
- } else if (digest.MocEnabled) {
- tools = "AUTOMOC";
- property = "SKIP_AUTOMOC";
- } else if (digest.UicEnabled) {
- tools = "AUTOUIC";
- property = "SKIP_AUTOUIC";
- }
- msg += "For compatibility, CMake is excluding the GENERATED source "
- "file(s):\n";
- for (const std::string& absFile : generatedHeaders) {
- msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
- }
- for (const std::string& absFile : generatedSources) {
- msg.append(" ").append(cmQtAutoGen::Quoted(absFile)).append("\n");
- }
- msg += "from processing by ";
- msg += tools;
- msg +=
- ". If any of the files should be processed, set CMP0071 to NEW. "
- "If any of the files should not be processed, "
- "explicitly exclude them by setting the source file property ";
- msg += property;
- msg += ":\n set_property(SOURCE file.h PROPERTY ";
- msg += property;
- msg += " ON)\n";
- makefile->IssueMessage(cmake::AUTHOR_WARNING, msg);
- }
- }
- }
- // Sort headers and sources
- std::sort(digest.Headers.begin(), digest.Headers.end());
- std::sort(digest.Sources.begin(), digest.Sources.end());
-
- // Process qrc files
- if (!digest.Qrcs.empty()) {
- const bool QtV5 = (digest.QtVersionMajor == "5");
- std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor);
- // Target rcc options
- std::vector<std::string> optionsTarget;
- cmSystemTools::ExpandListArgument(
- GetSafeProperty(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;
- break;
- }
- }
- }
- // Path checksum
- {
- cmFilePathChecksum const fpathCheckSum(makefile);
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
- qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile);
- // RCC output file name
- std::string rccFile = autogenBuildDir + "/";
- rccFile += qrcDigest.PathChecksum;
- rccFile += "/qrc_";
- rccFile += qrcDigest.QrcName;
- rccFile += ".cpp";
- qrcDigest.RccFile = std::move(rccFile);
- }
- }
- // RCC options
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
- // Target options
- std::vector<std::string> opts = optionsTarget;
- // Merge computed "-name XYZ" option
- {
- std::string name = qrcDigest.QrcName;
- // Replace '-' with '_'. The former is not valid for symbol names.
- std::replace(name.begin(), name.end(), '-', '_');
- if (!qrcDigest.Unique) {
- name += "_";
- name += qrcDigest.PathChecksum;
- }
- std::vector<std::string> nameOpts;
- nameOpts.emplace_back("-name");
- nameOpts.emplace_back(std::move(name));
- cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5);
- }
- // Merge file option
- cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5);
- qrcDigest.Options = std::move(opts);
- }
- for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) {
- // Register file at target
- {
- auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig,
- configsList, cmQtAutoGen::RCC);
- for (std::string& file : files) {
- autogenProvides.push_back(std::move(file));
- }
- }
- // Dependencies
- if (qrcDigest.Generated) {
- // Add the GENERATED .qrc file to the dependencies
- autogenDependFiles.insert(qrcDigest.QrcFile);
- } else {
- // Add the resource files to the dependencies
- {
- std::string error;
- if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc,
- qrcDigest.QrcFile,
- qrcDigest.Resources, &error)) {
- for (std::string const& fileName : qrcDigest.Resources) {
- autogenDependFiles.insert(fileName);
- }
- } else {
- cmSystemTools::Error(error.c_str());
- }
- }
- // Run cmake again when .qrc file changes
- makefile->AddCMakeDependFile(qrcDigest.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);
- }
- }
- }
- }
-
- // 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) {
- target->Target->AddUtility(depTarget->GetName(), makefile);
- }
-
- // 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 {
-
- // Add link library target dependencies to the autogen target dependencies
- {
- // add_dependencies/addUtility do not support generator expressions.
- // We depend only on the libraries found in all configs therefore.
- std::map<cmGeneratorTarget const*, std::size_t> commonTargets;
- 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)) {
- // Increment target config count
- commonTargets[libTarget]++;
- }
- }
- }
- }
- for (auto const& item : commonTargets) {
- if (item.second == configsList.size()) {
- autogenDependTargets.insert(item.first->Target);
- }
- }
- }
-
- // Create autogen target
- cmTarget* autogenTarget = makefile->AddUtilityCommand(
- autogenTargetName, true, workingDirectory.c_str(),
- /*byproducts=*/autogenProvides,
- std::vector<std::string>(autogenDependFiles.begin(),
- autogenDependFiles.end()),
- 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");
- }
- // Inherit FOLDER property from target (#13688)
- if (autogenFolder == nullptr) {
- autogenFolder = SafeString(target->Target->GetProperty("FOLDER"));
- }
- if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) {
- autogenTarget->SetProperty("FOLDER", autogenFolder);
- }
- }
-
- // Add autogen target to the origin target dependencies
- target->Target->AddUtility(autogenTargetName, makefile);
- }
-}
-
-void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
- cmQtAutoGenDigest const& digest)
-{
- cmGeneratorTarget const* target = digest.Target;
- cmMakefile* makefile = target->Target->GetMakefile();
- cmQtAutoGen::MultiConfig const multiConfig =
- AutogenMultiConfig(target->GetGlobalGenerator());
-
- // forget the variables added here afterwards again:
- cmMakefile::ScopePushPop varScope(makefile);
- static_cast<void>(varScope);
-
- // Configurations
- std::string configDefault;
- std::vector<std::string> configsList;
- std::map<std::string, std::string> configSuffixes;
- {
- configDefault = makefile->GetConfigurations(configsList);
- if (configsList.empty()) {
- configsList.push_back("");
- }
- }
- 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);
- }
- }
- if (digest.RccEnabled) {
- SetupAutoTargetRcc(digest);
- }
- }
-
- // 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
- // --------------------------------------
-
- // Ensure we have write permission in case .in was read-only.
- 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);
- if (!(perm & mode_write)) {
- cmSystemTools::SetPermissions(infoFile, perm | mode_write);
- }
-
- // Open and write file
- cmsys::ofstream ofs(infoFile.c_str(), std::ios::app);
- if (ofs) {
- 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";
- }
- };
- 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);
- } 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());
- }
- }
-}
diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h
deleted file mode 100644
index b8a5ae480..000000000
--- a/Source/cmQtAutoGeneratorInitializer.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#ifndef cmQtAutoGeneratorInitializer_h
-#define cmQtAutoGeneratorInitializer_h
-
-#include "cmConfigure.h" // IWYU pragma: keep
-#include "cmQtAutoGenDigest.h"
-
-#include <string>
-
-class cmGeneratorTarget;
-
-class cmQtAutoGeneratorInitializer
-{
-public:
- static std::string GetQtMajorVersion(cmGeneratorTarget const* target);
- static std::string GetQtMinorVersion(cmGeneratorTarget const* target,
- std::string const& qtVersionMajor);
-
- static void InitializeAutogenTarget(cmQtAutoGenDigest& digest);
- static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest);
-};
-
-#endif
diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx
new file mode 100644
index 000000000..6be65eea5
--- /dev/null
+++ b/Source/cmQtAutoGeneratorMocUic.cxx
@@ -0,0 +1,2028 @@
+/* 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 "cmQtAutoGeneratorMocUic.h"
+
+#include <algorithm>
+#include <array>
+#include <functional>
+#include <list>
+#include <memory>
+#include <sstream>
+#include <utility>
+
+#include "cmAlgorithms.h"
+#include "cmCryptoHash.h"
+#include "cmMakefile.h"
+#include "cmSystemTools.h"
+#include "cmake.h"
+
+#if defined(__APPLE__)
+#include <unistd.h>
+#endif
+
+// -- Class methods
+
+std::string cmQtAutoGeneratorMocUic::BaseSettingsT::AbsoluteBuildPath(
+ std::string const& relativePath) const
+{
+ return cmSystemTools::CollapseCombinedPath(AutogenBuildDir, relativePath);
+}
+
+/**
+ * @brief Tries to find the header file to the given file base path by
+ * appending different header extensions
+ * @return True on success
+ */
+bool cmQtAutoGeneratorMocUic::BaseSettingsT::FindHeader(
+ std::string& header, std::string const& testBasePath) const
+{
+ for (std::string const& ext : HeaderExtensions) {
+ std::string testFilePath(testBasePath);
+ testFilePath.push_back('.');
+ testFilePath += ext;
+ if (FileSys->FileExists(testFilePath)) {
+ header = testFilePath;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool cmQtAutoGeneratorMocUic::MocSettingsT::skipped(
+ std::string const& fileName) const
+{
+ return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+}
+
+/**
+ * @brief Returns the first relevant Qt macro name found in the given C++ code
+ * @return The name of the Qt macro or an empty string
+ */
+std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindMacro(
+ std::string const& content) const
+{
+ for (KeyExpT const& filter : MacroFilters) {
+ // Run a simple find string operation before the expensive
+ // regular expression check
+ if (content.find(filter.Key) != std::string::npos) {
+ cmsys::RegularExpressionMatch match;
+ if (filter.Exp.find(content.c_str(), match)) {
+ // Return macro name on demand
+ return filter.Key;
+ }
+ }
+ }
+ return std::string();
+}
+
+std::string cmQtAutoGeneratorMocUic::MocSettingsT::MacrosString() const
+{
+ std::string res;
+ const auto itB = MacroFilters.cbegin();
+ const auto itE = MacroFilters.cend();
+ const auto itL = itE - 1;
+ auto itC = itB;
+ for (; itC != itE; ++itC) {
+ // Separator
+ if (itC != itB) {
+ if (itC != itL) {
+ res += ", ";
+ } else {
+ res += " or ";
+ }
+ }
+ // Key
+ res += itC->Key;
+ }
+ return res;
+}
+
+std::string cmQtAutoGeneratorMocUic::MocSettingsT::FindIncludedFile(
+ std::string const& sourcePath, std::string const& includeString) const
+{
+ // Search in vicinity of the source
+ {
+ std::string testPath = sourcePath;
+ testPath += includeString;
+ if (FileSys->FileExists(testPath)) {
+ return FileSys->RealPath(testPath);
+ }
+ }
+ // Search in include directories
+ for (std::string const& path : IncludePaths) {
+ std::string fullPath = path;
+ fullPath.push_back('/');
+ fullPath += includeString;
+ if (FileSys->FileExists(fullPath)) {
+ return FileSys->RealPath(fullPath);
+ }
+ }
+ // Return empty string
+ return std::string();
+}
+
+void cmQtAutoGeneratorMocUic::MocSettingsT::FindDependencies(
+ std::string const& content, std::set<std::string>& depends) const
+{
+ if (!DependFilters.empty() && !content.empty()) {
+ for (KeyExpT const& filter : DependFilters) {
+ // Run a simple find string check
+ if (content.find(filter.Key) != std::string::npos) {
+ // Run the expensive regular expression check loop
+ const char* contentChars = content.c_str();
+ cmsys::RegularExpressionMatch match;
+ while (filter.Exp.find(contentChars, match)) {
+ {
+ std::string dep = match.match(1);
+ if (!dep.empty()) {
+ depends.emplace(std::move(dep));
+ }
+ }
+ contentChars += match.end();
+ }
+ }
+ }
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::UicSettingsT::skipped(
+ std::string const& fileName) const
+{
+ return (!Enabled || (SkipList.find(fileName) != SkipList.end()));
+}
+
+void cmQtAutoGeneratorMocUic::JobParseT::Process(WorkerT& wrk)
+{
+ if (AutoMoc && Header) {
+ // Don't parse header for moc if the file is included by a source already
+ if (wrk.Gen().ParallelMocIncluded(FileName)) {
+ AutoMoc = false;
+ }
+ }
+
+ if (AutoMoc || AutoUic) {
+ std::string error;
+ MetaT meta;
+ if (wrk.FileSys().FileRead(meta.Content, FileName, &error)) {
+ if (!meta.Content.empty()) {
+ meta.FileDir = SubDirPrefix(FileName);
+ meta.FileBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(FileName);
+
+ bool success = true;
+ if (AutoMoc) {
+ if (Header) {
+ success = ParseMocHeader(wrk, meta);
+ } else {
+ success = ParseMocSource(wrk, meta);
+ }
+ }
+ if (AutoUic && success) {
+ ParseUic(wrk, meta);
+ }
+ } else {
+ wrk.LogFileWarning(GeneratorT::GEN, FileName,
+ "The source file is empty");
+ }
+ } else {
+ wrk.LogFileError(GeneratorT::GEN, FileName,
+ "Could not read the file: " + error);
+ }
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocSource(WorkerT& wrk,
+ MetaT const& meta)
+{
+ struct JobPre
+ {
+ bool self; // source file is self
+ bool underscore; // "moc_" style include
+ std::string SourceFile;
+ std::string IncludeString;
+ };
+
+ struct MocInclude
+ {
+ std::string Inc; // full include string
+ std::string Dir; // include string directory
+ std::string Base; // include string file base
+ };
+
+ // Check if this source file contains a relevant macro
+ std::string const ownMacro = wrk.Moc().FindMacro(meta.Content);
+
+ // Extract moc includes from file
+ std::deque<MocInclude> mocIncsUsc;
+ std::deque<MocInclude> mocIncsDot;
+ {
+ if (meta.Content.find("moc") != std::string::npos) {
+ const char* contentChars = meta.Content.c_str();
+ cmsys::RegularExpressionMatch match;
+ while (wrk.Moc().RegExpInclude.find(contentChars, match)) {
+ std::string incString = match.match(2);
+ std::string incDir(SubDirPrefix(incString));
+ std::string incBase =
+ cmSystemTools::GetFilenameWithoutLastExtension(incString);
+ if (cmHasLiteralPrefix(incBase, "moc_")) {
+ // moc_<BASE>.cxx
+ // Remove the moc_ part from the base name
+ mocIncsUsc.emplace_back(MocInclude{
+ std::move(incString), std::move(incDir), incBase.substr(4) });
+ } else {
+ // <BASE>.moc
+ mocIncsDot.emplace_back(MocInclude{
+ std::move(incString), std::move(incDir), std::move(incBase) });
+ }
+ // Forward content pointer
+ contentChars += match.end();
+ }
+ }
+ }
+
+ // Check if there is anything to do
+ if (ownMacro.empty() && mocIncsUsc.empty() && mocIncsDot.empty()) {
+ return true;
+ }
+
+ bool ownDotMocIncluded = false;
+ bool ownMocUscIncluded = false;
+ std::deque<JobPre> jobs;
+
+ // Process moc_<BASE>.cxx includes
+ for (const MocInclude& mocInc : mocIncsUsc) {
+ std::string const header =
+ MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
+ if (!header.empty()) {
+ // Check if header is skipped
+ if (wrk.Moc().skipped(header)) {
+ continue;
+ }
+ // Register moc job
+ const bool ownMoc = (mocInc.Base == meta.FileBase);
+ jobs.emplace_back(JobPre{ ownMoc, true, header, mocInc.Inc });
+ // Store meta information for relaxed mode
+ if (ownMoc) {
+ ownMocUscIncluded = true;
+ }
+ } else {
+ {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += ", but the header ";
+ emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
+ emsg += " could not be found.";
+ wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
+ }
+ return false;
+ }
+ }
+
+ // Process <BASE>.moc includes
+ for (const MocInclude& mocInc : mocIncsDot) {
+ const bool ownMoc = (mocInc.Base == meta.FileBase);
+ if (wrk.Moc().RelaxedMode) {
+ // Relaxed mode
+ if (!ownMacro.empty() && ownMoc) {
+ // Add self
+ jobs.emplace_back(JobPre{ ownMoc, false, FileName, mocInc.Inc });
+ ownDotMocIncluded = true;
+ } else {
+ // In relaxed mode try to find a header instead but issue a warning.
+ // This is for KDE4 compatibility
+ std::string const header =
+ MocFindIncludedHeader(wrk, meta.FileDir, mocInc.Dir + mocInc.Base);
+ if (!header.empty()) {
+ // Check if header is skipped
+ if (wrk.Moc().skipped(header)) {
+ continue;
+ }
+ // Register moc job
+ jobs.emplace_back(JobPre{ ownMoc, false, header, mocInc.Inc });
+ if (ownMacro.empty()) {
+ if (ownMoc) {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += ", but does not contain a ";
+ emsg += wrk.Moc().MacrosString();
+ emsg += " macro.\nRunning moc on\n ";
+ emsg += Quoted(header);
+ emsg += "!\nBetter include ";
+ emsg += Quoted("moc_" + mocInc.Base + ".cpp");
+ emsg += " for a compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
+ wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
+ } else {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += " instead of ";
+ emsg += Quoted("moc_" + mocInc.Base + ".cpp");
+ emsg += ".\nRunning moc on\n ";
+ emsg += Quoted(header);
+ emsg += "!\nBetter include ";
+ emsg += Quoted("moc_" + mocInc.Base + ".cpp");
+ emsg += " for compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
+ wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
+ }
+ }
+ } else {
+ {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += ", which seems to be the moc file from a different "
+ "source file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a "
+ "matching header ";
+ emsg += Quoted(MocStringHeaders(wrk, mocInc.Base));
+ emsg += " could not be found.";
+ wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
+ }
+ return false;
+ }
+ }
+ } else {
+ // Strict mode
+ if (ownMoc) {
+ // Include self
+ jobs.emplace_back(JobPre{ ownMoc, false, FileName, mocInc.Inc });
+ ownDotMocIncluded = true;
+ // Accept but issue a warning if moc isn't required
+ if (ownMacro.empty()) {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += ", but does not contain a ";
+ emsg += wrk.Moc().MacrosString();
+ emsg += " macro.";
+ wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
+ }
+ } else {
+ // Don't allow <BASE>.moc include other than self in strict mode
+ {
+ std::string emsg = "The file includes the moc file ";
+ emsg += Quoted(mocInc.Inc);
+ emsg += ", which seems to be the moc file from a different "
+ "source file.\nThis is not supported. Include ";
+ emsg += Quoted(meta.FileBase + ".moc");
+ emsg += " to run moc on this source file.";
+ wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
+ }
+ return false;
+ }
+ }
+ }
+
+ if (!ownMacro.empty() && !ownDotMocIncluded) {
+ // In this case, check whether the scanned file itself contains a
+ // Q_OBJECT.
+ // If this is the case, the moc_foo.cpp should probably be generated from
+ // foo.cpp instead of foo.h, because otherwise it won't build.
+ // But warn, since this is not how it is supposed to be used.
+ // This is for KDE4 compatibility.
+ if (wrk.Moc().RelaxedMode && ownMocUscIncluded) {
+ JobPre uscJobPre;
+ // Remove underscore job request
+ {
+ auto itC = jobs.begin();
+ auto itE = jobs.end();
+ for (; itC != itE; ++itC) {
+ JobPre& job(*itC);
+ if (job.self && job.underscore) {
+ uscJobPre = std::move(job);
+ jobs.erase(itC);
+ break;
+ }
+ }
+ }
+ // Issue a warning
+ {
+ std::string emsg = "The file contains a ";
+ emsg += ownMacro;
+ emsg += " macro, but does not include ";
+ emsg += Quoted(meta.FileBase + ".moc");
+ emsg += ". Instead it includes ";
+ emsg += Quoted(uscJobPre.IncludeString);
+ emsg += ".\nRunning moc on\n ";
+ emsg += Quoted(FileName);
+ emsg += "!\nBetter include ";
+ emsg += Quoted(meta.FileBase + ".moc");
+ emsg += " for compatibility with strict mode.\n"
+ "(CMAKE_AUTOMOC_RELAXED_MODE warning)";
+ wrk.LogFileWarning(GeneratorT::MOC, FileName, emsg);
+ }
+ // Add own source job
+ jobs.emplace_back(
+ JobPre{ true, false, FileName, uscJobPre.IncludeString });
+ } else {
+ // Otherwise always error out since it will not compile.
+ {
+ std::string emsg = "The file contains a ";
+ emsg += ownMacro;
+ emsg += " macro, but does not include ";
+ emsg += Quoted(meta.FileBase + ".moc");
+ emsg += "!\nConsider to\n - add #include \"";
+ emsg += meta.FileBase;
+ emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file";
+ wrk.LogFileError(GeneratorT::MOC, FileName, emsg);
+ }
+ return false;
+ }
+ }
+
+ // Convert pre jobs to actual jobs
+ for (JobPre& jobPre : jobs) {
+ JobHandleT jobHandle(new JobMocT(std::move(jobPre.SourceFile), FileName,
+ std::move(jobPre.IncludeString)));
+ if (jobPre.self) {
+ // Read depdendencies from this source
+ static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
+ }
+ if (!wrk.Gen().ParallelJobPushMoc(jobHandle)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool cmQtAutoGeneratorMocUic::JobParseT::ParseMocHeader(WorkerT& wrk,
+ MetaT const& meta)
+{
+ bool success = true;
+ std::string const macroName = wrk.Moc().FindMacro(meta.Content);
+ if (!macroName.empty()) {
+ JobHandleT jobHandle(
+ new JobMocT(std::string(FileName), std::string(), std::string()));
+ // Read depdendencies from this source
+ static_cast<JobMocT&>(*jobHandle).FindDependencies(wrk, meta.Content);
+ success = wrk.Gen().ParallelJobPushMoc(jobHandle);
+ }
+ return success;
+}
+
+std::string cmQtAutoGeneratorMocUic::JobParseT::MocStringHeaders(
+ WorkerT& wrk, std::string const& fileBase) const
+{
+ std::string res = fileBase;
+ res += ".{";
+ res += cmJoin(wrk.Base().HeaderExtensions, ",");
+ res += "}";
+ return res;
+}
+
+std::string cmQtAutoGeneratorMocUic::JobParseT::MocFindIncludedHeader(
+ WorkerT& wrk, std::string const& includerDir, std::string const& includeBase)
+{
+ std::string header;
+ // Search in vicinity of the source
+ if (!wrk.Base().FindHeader(header, includerDir + includeBase)) {
+ // Search in include directories
+ for (std::string const& path : wrk.Moc().IncludePaths) {
+ std::string fullPath = path;
+ fullPath.push_back('/');
+ fullPath += includeBase;
+ if (wrk.Base().FindHeader(header, fullPath)) {
+ break;
+ }
+ }
+ }
+ // Sanitize
+ if (!header.empty()) {
+ header = wrk.FileSys().RealPath(header);
+ }
+ return header;
+}
+
+bool cmQtAutoGeneratorMocUic::JobParseT::ParseUic(WorkerT& wrk,
+ MetaT const& meta)
+{
+ bool success = true;
+ if (meta.Content.find("ui_") != std::string::npos) {
+ const char* contentChars = meta.Content.c_str();
+ cmsys::RegularExpressionMatch match;
+ while (wrk.Uic().RegExpInclude.find(contentChars, match)) {
+ if (!ParseUicInclude(wrk, meta, match.match(2))) {
+ success = false;
+ break;
+ }
+ contentChars += match.end();
+ }
+ }
+ return success;
+}
+
+bool cmQtAutoGeneratorMocUic::JobParseT::ParseUicInclude(
+ WorkerT& wrk, MetaT const& meta, std::string&& includeString)
+{
+ bool success = false;
+ std::string uiInputFile = UicFindIncludedFile(wrk, meta, includeString);
+ if (!uiInputFile.empty()) {
+ if (!wrk.Uic().skipped(uiInputFile)) {
+ JobHandleT jobHandle(new JobUicT(std::move(uiInputFile), FileName,
+ std::move(includeString)));
+ success = wrk.Gen().ParallelJobPushUic(jobHandle);
+ } else {
+ // A skipped file is successful
+ success = true;
+ }
+ }
+ return success;
+}
+
+std::string cmQtAutoGeneratorMocUic::JobParseT::UicFindIncludedFile(
+ WorkerT& wrk, MetaT const& meta, std::string const& includeString)
+{
+ std::string res;
+ std::string searchFile =
+ cmSystemTools::GetFilenameWithoutLastExtension(includeString).substr(3);
+ searchFile += ".ui";
+ // Collect search paths list
+ std::deque<std::string> testFiles;
+ {
+ std::string const searchPath = SubDirPrefix(includeString);
+
+ std::string searchFileFull;
+ if (!searchPath.empty()) {
+ searchFileFull = searchPath;
+ searchFileFull += searchFile;
+ }
+ // Vicinity of the source
+ {
+ std::string const sourcePath = meta.FileDir;
+ testFiles.push_back(sourcePath + searchFile);
+ if (!searchPath.empty()) {
+ testFiles.push_back(sourcePath + searchFileFull);
+ }
+ }
+ // AUTOUIC search paths
+ if (!wrk.Uic().SearchPaths.empty()) {
+ for (std::string const& sPath : wrk.Uic().SearchPaths) {
+ testFiles.push_back((sPath + "/").append(searchFile));
+ }
+ if (!searchPath.empty()) {
+ for (std::string const& sPath : wrk.Uic().SearchPaths) {
+ testFiles.push_back((sPath + "/").append(searchFileFull));
+ }
+ }
+ }
+ }
+
+ // Search for the .ui file!
+ for (std::string const& testFile : testFiles) {
+ if (wrk.FileSys().FileExists(testFile)) {
+ res = wrk.FileSys().RealPath(testFile);
+ break;
+ }
+ }
+
+ // Log error
+ if (res.empty()) {
+ std::string emsg = "Could not find ";
+ emsg += Quoted(searchFile);
+ emsg += " in\n";
+ for (std::string const& testFile : testFiles) {
+ emsg += " ";
+ emsg += Quoted(testFile);
+ emsg += "\n";
+ }
+ wrk.LogFileError(GeneratorT::UIC, FileName, emsg);
+ }
+
+ return res;
+}
+
+void cmQtAutoGeneratorMocUic::JobMocPredefsT::Process(WorkerT& wrk)
+{
+ // (Re)generate moc_predefs.h on demand
+ bool generate(false);
+ bool fileExists(wrk.FileSys().FileExists(wrk.Moc().PredefsFileAbs));
+ if (!fileExists) {
+ if (wrk.Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(wrk.Moc().PredefsFileRel);
+ reason += " because it doesn't exist";
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ generate = true;
+ } else if (wrk.Moc().SettingsChanged) {
+ if (wrk.Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(wrk.Moc().PredefsFileRel);
+ reason += " because the settings changed.";
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ generate = true;
+ }
+ if (generate) {
+ ProcessResultT result;
+ {
+ // Compose command
+ std::vector<std::string> cmd = wrk.Moc().PredefsCmd;
+ // Add includes
+ cmd.insert(cmd.end(), wrk.Moc().Includes.begin(),
+ wrk.Moc().Includes.end());
+ // Add definitions
+ for (std::string const& def : wrk.Moc().Definitions) {
+ cmd.push_back("-D" + def);
+ }
+ // Execute command
+ if (!wrk.RunProcess(GeneratorT::MOC, result, cmd)) {
+ std::string emsg = "The content generation command for ";
+ emsg += Quoted(wrk.Moc().PredefsFileRel);
+ emsg += " failed.\n";
+ emsg += result.ErrorMessage;
+ wrk.LogCommandError(GeneratorT::MOC, emsg, cmd, result.StdOut);
+ }
+ }
+
+ // (Re)write predefs file only on demand
+ if (!result.error()) {
+ if (!fileExists ||
+ wrk.FileSys().FileDiffers(wrk.Moc().PredefsFileAbs, result.StdOut)) {
+ if (wrk.FileSys().FileWrite(GeneratorT::MOC, wrk.Moc().PredefsFileAbs,
+ result.StdOut)) {
+ // Success
+ } else {
+ std::string emsg = "Writing ";
+ emsg += Quoted(wrk.Moc().PredefsFileRel);
+ emsg += " failed.";
+ wrk.LogFileError(GeneratorT::MOC, wrk.Moc().PredefsFileAbs, emsg);
+ }
+ } else {
+ // Touch to update the time stamp
+ if (wrk.Log().Verbose()) {
+ std::string msg = "Touching ";
+ msg += Quoted(wrk.Moc().PredefsFileRel);
+ msg += ".";
+ wrk.LogInfo(GeneratorT::MOC, msg);
+ }
+ wrk.FileSys().Touch(wrk.Moc().PredefsFileAbs);
+ }
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::JobMocT::FindDependencies(
+ WorkerT& wrk, std::string const& content)
+{
+ wrk.Moc().FindDependencies(content, Depends);
+ DependsValid = true;
+}
+
+void cmQtAutoGeneratorMocUic::JobMocT::Process(WorkerT& wrk)
+{
+ // Compute build file name
+ if (!IncludeString.empty()) {
+ BuildFile = wrk.Base().AutogenIncludeDir;
+ BuildFile += '/';
+ BuildFile += IncludeString;
+ } else {
+ std::string rel = wrk.Base().FilePathChecksum.getPart(SourceFile);
+ rel += "/moc_";
+ rel += cmSystemTools::GetFilenameWithoutLastExtension(SourceFile);
+ rel += ".cpp";
+ // Register relative file path
+ wrk.Gen().ParallelMocAutoRegister(rel);
+ // Absolute build path
+ if (wrk.Base().MultiConfig) {
+ BuildFile = wrk.Base().AutogenIncludeDir;
+ BuildFile += '/';
+ BuildFile += rel;
+ } else {
+ BuildFile = wrk.Base().AbsoluteBuildPath(rel);
+ }
+ }
+
+ if (UpdateRequired(wrk)) {
+ GenerateMoc(wrk);
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::JobMocT::UpdateRequired(WorkerT& wrk)
+{
+ bool const verbose = wrk.Gen().Log().Verbose();
+
+ // Test if the build file exists
+ if (!wrk.FileSys().FileExists(BuildFile)) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " from its source file ";
+ reason += Quoted(SourceFile);
+ reason += " because it doesn't exist";
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ return true;
+ }
+
+ // Test if any setting changed
+ if (wrk.Moc().SettingsChanged) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " from ";
+ reason += Quoted(SourceFile);
+ reason += " because the MOC settings changed";
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ return true;
+ }
+
+ // Test if the moc_predefs file is newer
+ if (!wrk.Moc().PredefsFileAbs.empty()) {
+ bool isOlder = false;
+ {
+ std::string error;
+ isOlder = wrk.FileSys().FileIsOlderThan(
+ BuildFile, wrk.Moc().PredefsFileAbs, &error);
+ if (!isOlder && !error.empty()) {
+ wrk.LogError(GeneratorT::MOC, error);
+ return false;
+ }
+ }
+ if (isOlder) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " because it's older than: ";
+ reason += Quoted(wrk.Moc().PredefsFileAbs);
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ return true;
+ }
+ }
+
+ // Test if the source file is newer
+ {
+ bool isOlder = false;
+ {
+ std::string error;
+ isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
+ if (!isOlder && !error.empty()) {
+ wrk.LogError(GeneratorT::MOC, error);
+ return false;
+ }
+ }
+ if (isOlder) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " because it's older than its source file ";
+ reason += Quoted(SourceFile);
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ return true;
+ }
+ }
+
+ // Test if a dependency file is newer
+ {
+ // Read dependencies on demand
+ if (!DependsValid) {
+ std::string content;
+ {
+ std::string error;
+ if (!wrk.FileSys().FileRead(content, SourceFile, &error)) {
+ std::string emsg = "Could not read file\n ";
+ emsg += Quoted(SourceFile);
+ emsg += "\nrequired by moc include ";
+ emsg += Quoted(IncludeString);
+ emsg += " in\n ";
+ emsg += Quoted(IncluderFile);
+ emsg += ".\n";
+ emsg += error;
+ wrk.LogError(GeneratorT::MOC, emsg);
+ return false;
+ }
+ }
+ FindDependencies(wrk, content);
+ }
+ // Check dependency timestamps
+ std::string error;
+ std::string sourceDir = SubDirPrefix(SourceFile);
+ for (std::string const& depFileRel : Depends) {
+ std::string depFileAbs =
+ wrk.Moc().FindIncludedFile(sourceDir, depFileRel);
+ if (!depFileAbs.empty()) {
+ if (wrk.FileSys().FileIsOlderThan(BuildFile, depFileAbs, &error)) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " from ";
+ reason += Quoted(SourceFile);
+ reason += " because it is older than it's dependency file ";
+ reason += Quoted(depFileAbs);
+ wrk.LogInfo(GeneratorT::MOC, reason);
+ }
+ return true;
+ }
+ if (!error.empty()) {
+ wrk.LogError(GeneratorT::MOC, error);
+ return false;
+ }
+ } else {
+ std::string message = "Could not find dependency file ";
+ message += Quoted(depFileRel);
+ wrk.LogFileWarning(GeneratorT::MOC, SourceFile, message);
+ }
+ }
+ }
+
+ return false;
+}
+
+void cmQtAutoGeneratorMocUic::JobMocT::GenerateMoc(WorkerT& wrk)
+{
+ // Make sure the parent directory exists
+ if (wrk.FileSys().MakeParentDirectory(GeneratorT::MOC, BuildFile)) {
+ // Compose moc command
+ std::vector<std::string> cmd;
+ cmd.push_back(wrk.Moc().Executable);
+ // Add options
+ cmd.insert(cmd.end(), wrk.Moc().AllOptions.begin(),
+ wrk.Moc().AllOptions.end());
+ // Add predefs include
+ if (!wrk.Moc().PredefsFileAbs.empty()) {
+ cmd.push_back("--include");
+ cmd.push_back(wrk.Moc().PredefsFileAbs);
+ }
+ cmd.push_back("-o");
+ cmd.push_back(BuildFile);
+ cmd.push_back(SourceFile);
+
+ // Execute moc command
+ ProcessResultT result;
+ if (wrk.RunProcess(GeneratorT::MOC, result, cmd)) {
+ // Moc command success
+ if (IncludeString.empty()) {
+ // Notify the generator that a not included file changed
+ wrk.Gen().ParallelMocAutoUpdated();
+ }
+ } else {
+ // Moc command failed
+ {
+ std::string emsg = "The moc process failed to compile\n ";
+ emsg += Quoted(SourceFile);
+ emsg += "\ninto\n ";
+ emsg += Quoted(BuildFile);
+ emsg += ".\n";
+ emsg += result.ErrorMessage;
+ wrk.LogCommandError(GeneratorT::MOC, emsg, cmd, result.StdOut);
+ }
+ wrk.FileSys().FileRemove(BuildFile);
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::JobUicT::Process(WorkerT& wrk)
+{
+ // Compute build file name
+ BuildFile = wrk.Base().AutogenIncludeDir;
+ BuildFile += '/';
+ BuildFile += IncludeString;
+
+ if (UpdateRequired(wrk)) {
+ GenerateUic(wrk);
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::JobUicT::UpdateRequired(WorkerT& wrk)
+{
+ bool const verbose = wrk.Gen().Log().Verbose();
+
+ // Test if the build file exists
+ if (!wrk.FileSys().FileExists(BuildFile)) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " from its source file ";
+ reason += Quoted(SourceFile);
+ reason += " because it doesn't exist";
+ wrk.LogInfo(GeneratorT::UIC, reason);
+ }
+ return true;
+ }
+
+ // Test if the uic settings changed
+ if (wrk.Uic().SettingsChanged) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " from ";
+ reason += Quoted(SourceFile);
+ reason += " because the UIC settings changed";
+ wrk.LogInfo(GeneratorT::UIC, reason);
+ }
+ return true;
+ }
+
+ // Test if the source file is newer
+ {
+ bool isOlder = false;
+ {
+ std::string error;
+ isOlder = wrk.FileSys().FileIsOlderThan(BuildFile, SourceFile, &error);
+ if (!isOlder && !error.empty()) {
+ wrk.LogError(GeneratorT::UIC, error);
+ return false;
+ }
+ }
+ if (isOlder) {
+ if (verbose) {
+ std::string reason = "Generating ";
+ reason += Quoted(BuildFile);
+ reason += " because it's older than its source file ";
+ reason += Quoted(SourceFile);
+ wrk.LogInfo(GeneratorT::UIC, reason);
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void cmQtAutoGeneratorMocUic::JobUicT::GenerateUic(WorkerT& wrk)
+{
+ // Make sure the parent directory exists
+ if (wrk.FileSys().MakeParentDirectory(GeneratorT::UIC, BuildFile)) {
+ // Compose uic command
+ std::vector<std::string> cmd;
+ cmd.push_back(wrk.Uic().Executable);
+ {
+ std::vector<std::string> allOpts = wrk.Uic().TargetOptions;
+ auto optionIt = wrk.Uic().Options.find(SourceFile);
+ if (optionIt != wrk.Uic().Options.end()) {
+ UicMergeOptions(allOpts, optionIt->second,
+ (wrk.Base().QtVersionMajor == 5));
+ }
+ cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
+ }
+ cmd.push_back("-o");
+ cmd.push_back(BuildFile);
+ cmd.push_back(SourceFile);
+
+ ProcessResultT result;
+ if (wrk.RunProcess(GeneratorT::UIC, result, cmd)) {
+ // Success
+ } else {
+ // Command failed
+ {
+ std::string emsg = "The uic process failed to compile\n ";
+ emsg += Quoted(SourceFile);
+ emsg += "\ninto\n ";
+ emsg += Quoted(BuildFile);
+ emsg += "\nincluded by\n ";
+ emsg += Quoted(IncluderFile);
+ emsg += ".\n";
+ emsg += result.ErrorMessage;
+ wrk.LogCommandError(GeneratorT::UIC, emsg, cmd, result.StdOut);
+ }
+ wrk.FileSys().FileRemove(BuildFile);
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::JobDeleterT::operator()(JobT* job)
+{
+ delete job;
+}
+
+cmQtAutoGeneratorMocUic::WorkerT::WorkerT(cmQtAutoGeneratorMocUic* gen,
+ uv_loop_t* uvLoop)
+ : Gen_(gen)
+{
+ // Initialize uv asynchronous callback for process starting
+ ProcessRequest_.init(*uvLoop, &WorkerT::UVProcessStart, this);
+ // Start thread
+ Thread_ = std::thread(&WorkerT::Loop, this);
+}
+
+cmQtAutoGeneratorMocUic::WorkerT::~WorkerT()
+{
+ // Join thread
+ if (Thread_.joinable()) {
+ Thread_.join();
+ }
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogInfo(
+ GeneratorT genType, std::string const& message) const
+{
+ return Log().Info(genType, message);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogWarning(
+ GeneratorT genType, std::string const& message) const
+{
+ return Log().Warning(genType, message);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogFileWarning(
+ GeneratorT genType, std::string const& filename,
+ std::string const& message) const
+{
+ return Log().WarningFile(genType, filename, message);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogError(
+ GeneratorT genType, std::string const& message) const
+{
+ Gen().ParallelRegisterJobError();
+ Log().Error(genType, message);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogFileError(
+ GeneratorT genType, std::string const& filename,
+ std::string const& message) const
+{
+ Gen().ParallelRegisterJobError();
+ Log().ErrorFile(genType, filename, message);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::LogCommandError(
+ GeneratorT genType, std::string const& message,
+ std::vector<std::string> const& command, std::string const& output) const
+{
+ Gen().ParallelRegisterJobError();
+ Log().ErrorCommand(genType, message, command, output);
+}
+
+bool cmQtAutoGeneratorMocUic::WorkerT::RunProcess(
+ GeneratorT genType, ProcessResultT& result,
+ std::vector<std::string> const& command)
+{
+ if (command.empty()) {
+ return false;
+ }
+
+ // Create process instance
+ {
+ std::lock_guard<std::mutex> lock(ProcessMutex_);
+ Process_ = cm::make_unique<ReadOnlyProcessT>();
+ Process_->setup(&result, true, command, Gen().Base().AutogenBuildDir);
+ }
+
+ // Send asynchronous process start request to libuv loop
+ ProcessRequest_.send();
+
+ // Log command
+ if (this->Log().Verbose()) {
+ std::string msg = "Running command:\n";
+ msg += QuotedCommand(command);
+ msg += '\n';
+ this->LogInfo(genType, msg);
+ }
+
+ // Wait until the process has been finished and destroyed
+ {
+ std::unique_lock<std::mutex> ulock(ProcessMutex_);
+ while (Process_) {
+ ProcessCondition_.wait(ulock);
+ }
+ }
+ return !result.error();
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::Loop()
+{
+ while (true) {
+ Gen().WorkerSwapJob(JobHandle_);
+ if (JobHandle_) {
+ JobHandle_->Process(*this);
+ } else {
+ break;
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::UVProcessStart(uv_async_t* handle)
+{
+ auto& wrk = *reinterpret_cast<WorkerT*>(handle->data);
+ {
+ std::lock_guard<std::mutex> lock(wrk.ProcessMutex_);
+ if (wrk.Process_ && !wrk.Process_->IsStarted()) {
+ wrk.Process_->start(handle->loop,
+ std::bind(&WorkerT::UVProcessFinished, &wrk));
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::WorkerT::UVProcessFinished()
+{
+ {
+ std::lock_guard<std::mutex> lock(ProcessMutex_);
+ if (Process_ && Process_->IsFinished()) {
+ Process_.reset();
+ }
+ }
+ // Notify idling thread
+ ProcessCondition_.notify_one();
+}
+
+cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic()
+ : Base_(&FileSys())
+ , Moc_(&FileSys())
+ , Stage_(StageT::SETTINGS_READ)
+ , JobsRemain_(0)
+ , JobError_(false)
+ , JobThreadsAbort_(false)
+ , MocAutoFileUpdated_(false)
+{
+ // Precompile regular expressions
+ Moc_.RegExpInclude.compile(
+ "(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
+ Uic_.RegExpInclude.compile("(^|\n)[ \t]*#[ \t]*include[ \t]+"
+ "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]");
+
+ // Initialize libuv asynchronous iteration request
+ UVRequest().init(*UVLoop(), &cmQtAutoGeneratorMocUic::UVPollStage, this);
+}
+
+cmQtAutoGeneratorMocUic::~cmQtAutoGeneratorMocUic()
+{
+}
+
+bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile)
+{
+ // -- Meta
+ Base_.HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
+
+ // Utility lambdas
+ auto InfoGet = [makefile](const char* key) {
+ return makefile->GetSafeDefinition(key);
+ };
+ auto InfoGetBool = [makefile](const char* key) {
+ return makefile->IsOn(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 InfoGetLists =
+ [makefile](const char* key) -> std::vector<std::vector<std::string>> {
+ std::vector<std::vector<std::string>> lists;
+ {
+ std::string const value = makefile->GetSafeDefinition(key);
+ std::string::size_type pos = 0;
+ while (pos < value.size()) {
+ std::string::size_type next = value.find(ListSep, pos);
+ std::string::size_type length =
+ (next != std::string::npos) ? next - pos : value.size() - pos;
+ // Remove enclosing braces
+ if (length >= 2) {
+ std::string::const_iterator itBeg = value.begin() + (pos + 1);
+ std::string::const_iterator itEnd = itBeg + (length - 2);
+ {
+ std::string subValue(itBeg, itEnd);
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(subValue, list);
+ lists.push_back(std::move(list));
+ }
+ }
+ pos += length;
+ pos += ListSep.size();
+ }
+ }
+ return lists;
+ };
+ auto InfoGetConfig = [makefile, this](const char* key) -> std::string {
+ const char* valueConf = nullptr;
+ {
+ std::string keyConf = key;
+ keyConf += '_';
+ keyConf += InfoConfig();
+ 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(InfoFile().c_str())) {
+ Log().ErrorFile(GeneratorT::GEN, InfoFile(), "File processing failed");
+ return false;
+ }
+
+ // -- Meta
+ Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG");
+ {
+ unsigned long num = Base_.NumThreads;
+ if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) {
+ num = std::max<unsigned long>(num, 1);
+ num = std::min<unsigned long>(num, ParallelMax);
+ Base_.NumThreads = static_cast<unsigned int>(num);
+ }
+ }
+
+ // - Files and directories
+ Base_.ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
+ Base_.ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
+ Base_.CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
+ Base_.CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
+ Base_.IncludeProjectDirsBefore =
+ InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
+ Base_.AutogenBuildDir = InfoGet("AM_BUILD_DIR");
+ if (Base_.AutogenBuildDir.empty()) {
+ Log().ErrorFile(GeneratorT::GEN, InfoFile(),
+ "Autogen build directory missing");
+ return false;
+ }
+ // include directory
+ {
+ std::string dirRel = InfoGetConfig("AM_INCLUDE_DIR");
+ if (dirRel.empty()) {
+ Log().ErrorFile(GeneratorT::GEN, InfoFile(),
+ "Autogen include directory missing");
+ return false;
+ }
+ Base_.AutogenIncludeDir = Base_.AbsoluteBuildPath(dirRel);
+ }
+
+ // - Files
+ SettingsFile_ = InfoGetConfig("AM_SETTINGS_FILE");
+ if (SettingsFile_.empty()) {
+ Log().ErrorFile(GeneratorT::GEN, InfoFile(), "Settings file name missing");
+ return false;
+ }
+
+ // - Qt environment
+ {
+ unsigned long qtv = Base_.QtVersionMajor;
+ if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) {
+ Base_.QtVersionMajor = static_cast<unsigned int>(qtv);
+ }
+ }
+
+ // - Moc
+ Moc_.Executable = InfoGet("AM_QT_MOC_EXECUTABLE");
+ Moc_.Enabled = !Moc().Executable.empty();
+ if (Moc().Enabled) {
+ {
+ auto lst = InfoGetList("AM_MOC_SKIP");
+ Moc_.SkipList.insert(lst.begin(), lst.end());
+ }
+ Moc_.Definitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
+#ifdef _WIN32
+ {
+ std::string win32("WIN32");
+ auto itB = Moc().Definitions.cbegin();
+ auto itE = Moc().Definitions.cend();
+ if (std::find(itB, itE, win32) == itE) {
+ Moc_.Definitions.emplace_back(std::move(win32));
+ }
+ }
+#endif
+ Moc_.IncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
+ Moc_.Options = InfoGetList("AM_MOC_OPTIONS");
+ Moc_.RelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
+ for (std::string const& item : InfoGetList("AM_MOC_MACRO_NAMES")) {
+ Moc_.MacroFilters.emplace_back(
+ item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
+ }
+ {
+ auto pushFilter = [this](std::string const& key, std::string const& exp,
+ std::string& error) {
+ if (!key.empty()) {
+ if (!exp.empty()) {
+ Moc_.DependFilters.push_back(KeyExpT());
+ KeyExpT& filter(Moc_.DependFilters.back());
+ if (filter.Exp.compile(exp)) {
+ filter.Key = key;
+ } else {
+ error = "Regular expression compiling failed";
+ }
+ } else {
+ error = "Regular expression is empty";
+ }
+ } else {
+ error = "Key is empty";
+ }
+ if (!error.empty()) {
+ error = ("AUTOMOC_DEPEND_FILTERS: " + error);
+ error += "\n";
+ error += " Key: ";
+ error += Quoted(key);
+ error += "\n";
+ error += " Exp: ";
+ error += Quoted(exp);
+ error += "\n";
+ }
+ };
+
+ std::string error;
+ // Insert default filter for Q_PLUGIN_METADATA
+ if (Base().QtVersionMajor != 4) {
+ pushFilter("Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
+ "[^\\)]*FILE[ \t]*\"([^\"]+)\"",
+ error);
+ }
+ // Insert user defined dependency filters
+ {
+ std::vector<std::string> flts = InfoGetList("AM_MOC_DEPEND_FILTERS");
+ if ((flts.size() % 2) == 0) {
+ for (std::vector<std::string>::iterator itC = flts.begin(),
+ itE = flts.end();
+ itC != itE; itC += 2) {
+ pushFilter(*itC, *(itC + 1), error);
+ if (!error.empty()) {
+ break;
+ }
+ }
+ } else {
+ Log().ErrorFile(
+ GeneratorT::MOC, InfoFile(),
+ "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
+ return false;
+ }
+ }
+ if (!error.empty()) {
+ Log().ErrorFile(GeneratorT::MOC, InfoFile(), error);
+ return false;
+ }
+ }
+ Moc_.PredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
+ // Install moc predefs job
+ if (!Moc().PredefsCmd.empty()) {
+ JobQueues_.MocPredefs.emplace_back(new JobMocPredefsT());
+ }
+ }
+
+ // - Uic
+ Uic_.Executable = InfoGet("AM_QT_UIC_EXECUTABLE");
+ Uic_.Enabled = !Uic().Executable.empty();
+ if (Uic().Enabled) {
+ {
+ auto lst = InfoGetList("AM_UIC_SKIP");
+ Uic_.SkipList.insert(lst.begin(), lst.end());
+ }
+ Uic_.SearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
+ Uic_.TargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
+ {
+ auto sources = InfoGetList("AM_UIC_OPTIONS_FILES");
+ auto options = InfoGetLists("AM_UIC_OPTIONS_OPTIONS");
+ // Compare list sizes
+ if (sources.size() != options.size()) {
+ std::ostringstream ost;
+ ost << "files/options lists sizes missmatch (" << sources.size() << "/"
+ << options.size() << ")";
+ Log().ErrorFile(GeneratorT::UIC, InfoFile(), ost.str());
+ return false;
+ }
+ auto fitEnd = sources.cend();
+ auto fit = sources.begin();
+ auto oit = options.begin();
+ while (fit != fitEnd) {
+ Uic_.Options[*fit] = std::move(*oit);
+ ++fit;
+ ++oit;
+ }
+ }
+ }
+
+ // Initialize source file jobs
+ {
+ std::hash<std::string> stringHash;
+ std::set<std::size_t> uniqueHeaders;
+
+ // Add header jobs
+ for (std::string& hdr : InfoGetList("AM_HEADERS")) {
+ const bool moc = !Moc().skipped(hdr);
+ const bool uic = !Uic().skipped(hdr);
+ if ((moc || uic) && uniqueHeaders.emplace(stringHash(hdr)).second) {
+ JobQueues_.Headers.emplace_back(
+ new JobParseT(std::move(hdr), moc, uic, true));
+ }
+ }
+ // Add source jobs
+ {
+ std::vector<std::string> sources = InfoGetList("AM_SOURCES");
+ // Add header(s) for the source file
+ for (std::string& src : sources) {
+ const bool srcMoc = !Moc().skipped(src);
+ const bool srcUic = !Uic().skipped(src);
+ if (!srcMoc && !srcUic) {
+ continue;
+ }
+ // Search for the default header file and a private header
+ {
+ std::array<std::string, 2> bases;
+ bases[0] = SubDirPrefix(src);
+ bases[0] += cmSystemTools::GetFilenameWithoutLastExtension(src);
+ bases[1] = bases[0];
+ bases[1] += "_p";
+ for (std::string const& headerBase : bases) {
+ std::string header;
+ if (Base().FindHeader(header, headerBase)) {
+ const bool moc = srcMoc && !Moc().skipped(header);
+ const bool uic = srcUic && !Uic().skipped(header);
+ if ((moc || uic) &&
+ uniqueHeaders.emplace(stringHash(header)).second) {
+ JobQueues_.Headers.emplace_back(
+ new JobParseT(std::move(header), moc, uic, true));
+ }
+ }
+ }
+ }
+ // Add source job
+ JobQueues_.Sources.emplace_back(
+ new JobParseT(std::move(src), srcMoc, srcUic));
+ }
+ }
+ }
+
+ // Init derived information
+ // ------------------------
+
+ // Init file path checksum generator
+ Base_.FilePathChecksum.setupParentDirs(
+ Base().CurrentSourceDir, Base().CurrentBinaryDir, Base().ProjectSourceDir,
+ Base().ProjectBinaryDir);
+
+ // Moc variables
+ if (Moc().Enabled) {
+ // Mocs compilation file
+ Moc_.CompFileAbs = Base().AbsoluteBuildPath("mocs_compilation.cpp");
+
+ // Moc predefs file
+ if (!Moc_.PredefsCmd.empty()) {
+ Moc_.PredefsFileRel = "moc_predefs";
+ if (Base_.MultiConfig) {
+ Moc_.PredefsFileRel += '_';
+ Moc_.PredefsFileRel += InfoConfig();
+ }
+ Moc_.PredefsFileRel += ".h";
+ Moc_.PredefsFileAbs = Base_.AbsoluteBuildPath(Moc().PredefsFileRel);
+ }
+
+ // Sort include directories on demand
+ if (Base().IncludeProjectDirsBefore) {
+ // Move strings to temporary list
+ std::list<std::string> includes;
+ includes.insert(includes.end(), Moc().IncludePaths.begin(),
+ Moc().IncludePaths.end());
+ Moc_.IncludePaths.clear();
+ Moc_.IncludePaths.reserve(includes.size());
+ // Append project directories only
+ {
+ std::array<std::string const*, 2> const movePaths = {
+ { &Base().ProjectBinaryDir, &Base().ProjectSourceDir }
+ };
+ for (std::string const* ppath : movePaths) {
+ std::list<std::string>::iterator it = includes.begin();
+ while (it != includes.end()) {
+ std::string const& path = *it;
+ if (cmSystemTools::StringStartsWith(path, ppath->c_str())) {
+ Moc_.IncludePaths.push_back(path);
+ it = includes.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+ }
+ // Append remaining directories
+ Moc_.IncludePaths.insert(Moc_.IncludePaths.end(), includes.begin(),
+ includes.end());
+ }
+ // Compose moc includes list
+ {
+ std::set<std::string> frameworkPaths;
+ for (std::string const& path : Moc().IncludePaths) {
+ Moc_.Includes.push_back("-I" + path);
+ // Extract framework path
+ if (cmHasLiteralSuffix(path, ".framework/Headers")) {
+ // Go up twice to get to the framework root
+ std::vector<std::string> pathComponents;
+ cmSystemTools::SplitPath(path, pathComponents);
+ std::string frameworkPath = cmSystemTools::JoinPath(
+ pathComponents.begin(), pathComponents.end() - 2);
+ frameworkPaths.insert(frameworkPath);
+ }
+ }
+ // Append framework includes
+ for (std::string const& path : frameworkPaths) {
+ Moc_.Includes.push_back("-F");
+ Moc_.Includes.push_back(path);
+ }
+ }
+ // Setup single list with all options
+ {
+ // Add includes
+ Moc_.AllOptions.insert(Moc_.AllOptions.end(), Moc().Includes.begin(),
+ Moc().Includes.end());
+ // Add definitions
+ for (std::string const& def : Moc().Definitions) {
+ Moc_.AllOptions.push_back("-D" + def);
+ }
+ // Add options
+ Moc_.AllOptions.insert(Moc_.AllOptions.end(), Moc().Options.begin(),
+ Moc().Options.end());
+ }
+ }
+
+ return true;
+}
+
+bool cmQtAutoGeneratorMocUic::Process()
+{
+ // Run libuv event loop
+ UVRequest().send();
+ if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
+ if (JobError_) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void cmQtAutoGeneratorMocUic::UVPollStage(uv_async_t* handle)
+{
+ reinterpret_cast<cmQtAutoGeneratorMocUic*>(handle->data)->PollStage();
+}
+
+void cmQtAutoGeneratorMocUic::PollStage()
+{
+ switch (Stage_) {
+ case StageT::SETTINGS_READ:
+ SettingsFileRead();
+ SetStage(StageT::CREATE_DIRECTORIES);
+ break;
+ case StageT::CREATE_DIRECTORIES:
+ CreateDirectories();
+ SetStage(StageT::PARSE_SOURCES);
+ break;
+ case StageT::PARSE_SOURCES:
+ if (ThreadsStartJobs(JobQueues_.Sources)) {
+ SetStage(StageT::PARSE_HEADERS);
+ }
+ break;
+ case StageT::PARSE_HEADERS:
+ if (ThreadsStartJobs(JobQueues_.Headers)) {
+ SetStage(StageT::MOC_PREDEFS);
+ }
+ break;
+ case StageT::MOC_PREDEFS:
+ if (ThreadsStartJobs(JobQueues_.MocPredefs)) {
+ SetStage(StageT::MOC_PROCESS);
+ }
+ break;
+ case StageT::MOC_PROCESS:
+ if (ThreadsStartJobs(JobQueues_.Moc)) {
+ SetStage(StageT::MOCS_COMPILATION);
+ }
+ break;
+ case StageT::MOCS_COMPILATION:
+ if (ThreadsJobsDone()) {
+ MocGenerateCompilation();
+ SetStage(StageT::UIC_PROCESS);
+ }
+ break;
+ case StageT::UIC_PROCESS:
+ if (ThreadsStartJobs(JobQueues_.Uic)) {
+ SetStage(StageT::SETTINGS_WRITE);
+ }
+ break;
+ case StageT::SETTINGS_WRITE:
+ SettingsFileWrite();
+ SetStage(StageT::FINISH);
+ break;
+ case StageT::FINISH:
+ if (ThreadsJobsDone()) {
+ // Clear all libuv handles
+ ThreadsStop();
+ UVRequest().reset();
+ // Set highest END stage manually
+ Stage_ = StageT::END;
+ }
+ break;
+ case StageT::END:
+ break;
+ }
+}
+
+void cmQtAutoGeneratorMocUic::SetStage(StageT stage)
+{
+ if (JobError_) {
+ stage = StageT::FINISH;
+ }
+ // Only allow to increase the stage
+ if (Stage_ < stage) {
+ Stage_ = stage;
+ UVRequest().send();
+ }
+}
+
+void cmQtAutoGeneratorMocUic::SettingsFileRead()
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+ std::string const sep(" ~~~ ");
+ if (Moc_.Enabled) {
+ std::string str;
+ str += Moc().Executable;
+ str += sep;
+ str += cmJoin(Moc().AllOptions, ";");
+ str += sep;
+ str += Base().IncludeProjectDirsBefore ? "TRUE" : "FALSE";
+ str += sep;
+ str += cmJoin(Moc().PredefsCmd, ";");
+ str += sep;
+ SettingsStringMoc_ = crypt.HashString(str);
+ }
+ if (Uic().Enabled) {
+ std::string str;
+ str += Uic().Executable;
+ str += sep;
+ str += cmJoin(Uic().TargetOptions, ";");
+ for (const auto& item : Uic().Options) {
+ str += sep;
+ str += item.first;
+ str += sep;
+ str += cmJoin(item.second, ";");
+ }
+ str += sep;
+ SettingsStringUic_ = crypt.HashString(str);
+ }
+ }
+
+ // Read old settings and compare
+ {
+ std::string content;
+ if (FileSys().FileRead(content, SettingsFile_)) {
+ if (Moc().Enabled) {
+ if (SettingsStringMoc_ != SettingsFind(content, "moc")) {
+ Moc_.SettingsChanged = true;
+ }
+ }
+ if (Uic().Enabled) {
+ if (SettingsStringUic_ != SettingsFind(content, "uic")) {
+ Uic_.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 (Moc().SettingsChanged || Uic().SettingsChanged) {
+ FileSys().FileRemove(SettingsFile_);
+ }
+ } else {
+ // Settings file read failed
+ if (Moc().Enabled) {
+ Moc_.SettingsChanged = true;
+ }
+ if (Uic().Enabled) {
+ Uic_.SettingsChanged = true;
+ }
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::SettingsFileWrite()
+{
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ // Only write if any setting changed
+ if (!JobError_ && (Moc().SettingsChanged || Uic().SettingsChanged)) {
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::GEN,
+ "Writing settings file " + Quoted(SettingsFile_));
+ }
+ // Compose settings file content
+ std::string content;
+ {
+ auto SettingAppend = [&content](const char* key,
+ std::string const& value) {
+ if (!value.empty()) {
+ content += key;
+ content += ':';
+ content += value;
+ content += '\n';
+ }
+ };
+ SettingAppend("moc", SettingsStringMoc_);
+ SettingAppend("uic", SettingsStringUic_);
+ }
+ // Write settings file
+ if (!FileSys().FileWrite(GeneratorT::GEN, SettingsFile_, content)) {
+ Log().ErrorFile(GeneratorT::GEN, SettingsFile_,
+ "Settings file writing failed");
+ // Remove old settings file to trigger a full rebuild on the next run
+ FileSys().FileRemove(SettingsFile_);
+ RegisterJobError();
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::CreateDirectories()
+{
+ // Create AUTOGEN include directory
+ if (!FileSys().MakeDirectory(GeneratorT::GEN, Base().AutogenIncludeDir)) {
+ RegisterJobError();
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::ThreadsStartJobs(JobQueueT& queue)
+{
+ bool done = false;
+ std::size_t queueSize = queue.size();
+
+ // Change the active queue
+ {
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ // Check if there are still unfinished jobs from the previous queue
+ if (JobsRemain_ == 0) {
+ if (!JobThreadsAbort_) {
+ JobQueue_.swap(queue);
+ JobsRemain_ = queueSize;
+ } else {
+ // Abort requested
+ queue.clear();
+ queueSize = 0;
+ }
+ done = true;
+ }
+ }
+
+ if (done && (queueSize != 0)) {
+ // Start new threads on demand
+ if (Workers_.empty()) {
+ Workers_.resize(Base().NumThreads);
+ for (auto& item : Workers_) {
+ item = cm::make_unique<WorkerT>(this, UVLoop());
+ }
+ } else {
+ // Notify threads
+ if (queueSize == 1) {
+ JobsConditionRead_.notify_one();
+ } else {
+ JobsConditionRead_.notify_all();
+ }
+ }
+ }
+
+ return done;
+}
+
+void cmQtAutoGeneratorMocUic::ThreadsStop()
+{
+ if (!Workers_.empty()) {
+ // Clear all jobs
+ {
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ JobThreadsAbort_ = true;
+ JobsRemain_ -= JobQueue_.size();
+ JobQueue_.clear();
+
+ JobQueues_.Sources.clear();
+ JobQueues_.Headers.clear();
+ JobQueues_.MocPredefs.clear();
+ JobQueues_.Moc.clear();
+ JobQueues_.Uic.clear();
+ }
+ // Wake threads
+ JobsConditionRead_.notify_all();
+ // Join and clear threads
+ Workers_.clear();
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::ThreadsJobsDone()
+{
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ return (JobsRemain_ == 0);
+}
+
+void cmQtAutoGeneratorMocUic::WorkerSwapJob(JobHandleT& jobHandle)
+{
+ bool const jobProcessed(jobHandle);
+ if (jobProcessed) {
+ jobHandle.reset(nullptr);
+ }
+ {
+ std::unique_lock<std::mutex> jobsLock(JobsMutex_);
+ // Reduce the remaining job count and notify the libuv loop
+ // when all jobs are done
+ if (jobProcessed) {
+ --JobsRemain_;
+ if (JobsRemain_ == 0) {
+ UVRequest().send();
+ }
+ }
+ // Wait for new jobs
+ while (!JobThreadsAbort_ && JobQueue_.empty()) {
+ JobsConditionRead_.wait(jobsLock);
+ }
+ // Try to pick up a new job handle
+ if (!JobThreadsAbort_ && !JobQueue_.empty()) {
+ jobHandle = std::move(JobQueue_.front());
+ JobQueue_.pop_front();
+ }
+ }
+}
+
+void cmQtAutoGeneratorMocUic::ParallelRegisterJobError()
+{
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ RegisterJobError();
+}
+
+// Private method that requires cmQtAutoGeneratorMocUic::JobsMutex_ to be
+// locked
+void cmQtAutoGeneratorMocUic::RegisterJobError()
+{
+ JobError_ = true;
+ if (!JobThreadsAbort_) {
+ JobThreadsAbort_ = true;
+ // Clear remaining jobs
+ if (JobsRemain_ != 0) {
+ JobsRemain_ -= JobQueue_.size();
+ JobQueue_.clear();
+ }
+ }
+}
+
+bool cmQtAutoGeneratorMocUic::ParallelJobPushMoc(JobHandleT& jobHandle)
+{
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ if (!JobThreadsAbort_) {
+ bool pushJobHandle = true;
+ // Do additional tests if this is an included moc job
+ const JobMocT& mocJob(static_cast<JobMocT&>(*jobHandle));
+ if (!mocJob.IncludeString.empty()) {
+ // Register included moc file and look for collisions
+ MocIncludedFiles_.emplace(mocJob.SourceFile);
+ if (!MocIncludedStrings_.emplace(mocJob.IncludeString).second) {
+ // Another source file includes the same moc file!
+ for (const JobHandleT& otherHandle : JobQueues_.Moc) {
+ const JobMocT& otherJob(static_cast<JobMocT&>(*otherHandle));
+ if (otherJob.IncludeString == mocJob.IncludeString) {
+ // Check if the same moc file would be generated from different
+ // source files which is an error.
+ if (otherJob.SourceFile != mocJob.SourceFile) {
+ // Include string collision
+ std::string error = "The two source files\n ";
+ error += Quoted(mocJob.IncluderFile);
+ error += " and\n ";
+ error += Quoted(otherJob.IncluderFile);
+ error += "\ncontain the the same moc include string ";
+ error += Quoted(mocJob.IncludeString);
+ error += "\nbut the moc file would be generated from different "
+ "source files\n ";
+ error += Quoted(mocJob.SourceFile);
+ error += " and\n ";
+ error += Quoted(otherJob.SourceFile);
+ error += ".\nConsider to\n"
+ "- not include the \"moc_<NAME>.cpp\" file\n"
+ "- add a directory prefix to a \"<NAME>.moc\" include "
+ "(e.g \"sub/<NAME>.moc\")\n"
+ "- rename the source file(s)\n";
+ Log().Error(GeneratorT::MOC, error);
+ RegisterJobError();
+ }
+ // Do not push this job in since the included moc file already
+ // gets generated by an other job.
+ pushJobHandle = false;
+ break;
+ }
+ }
+ }
+ }
+ // Push job on demand
+ if (pushJobHandle) {
+ JobQueues_.Moc.emplace_back(std::move(jobHandle));
+ }
+ }
+ return !JobError_;
+}
+
+bool cmQtAutoGeneratorMocUic::ParallelJobPushUic(JobHandleT& jobHandle)
+{
+ std::lock_guard<std::mutex> jobsLock(JobsMutex_);
+ if (!JobThreadsAbort_) {
+ bool pushJobHandle = true;
+ // Look for include collisions.
+ const JobUicT& uicJob(static_cast<JobUicT&>(*jobHandle));
+ for (const JobHandleT& otherHandle : JobQueues_.Uic) {
+ const JobUicT& otherJob(static_cast<JobUicT&>(*otherHandle));
+ if (otherJob.IncludeString == uicJob.IncludeString) {
+ // Check if the same uic file would be generated from different
+ // source files which would be an error.
+ if (otherJob.SourceFile != uicJob.SourceFile) {
+ // Include string collision
+ std::string error = "The two source files\n ";
+ error += Quoted(uicJob.IncluderFile);
+ error += " and\n ";
+ error += Quoted(otherJob.IncluderFile);
+ error += "\ncontain the the same uic include string ";
+ error += Quoted(uicJob.IncludeString);
+ error += "\nbut the uic file would be generated from different "
+ "source files\n ";
+ error += Quoted(uicJob.SourceFile);
+ error += " and\n ";
+ error += Quoted(otherJob.SourceFile);
+ error +=
+ ".\nConsider to\n"
+ "- add a directory prefix to a \"ui_<NAME>.h\" include "
+ "(e.g \"sub/ui_<NAME>.h\")\n"
+ "- rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
+ "include(s)\n";
+ Log().Error(GeneratorT::UIC, error);
+ RegisterJobError();
+ }
+ // Do not push this job in since the uic file already
+ // gets generated by an other job.
+ pushJobHandle = false;
+ break;
+ }
+ }
+ if (pushJobHandle) {
+ JobQueues_.Uic.emplace_back(std::move(jobHandle));
+ }
+ }
+ return !JobError_;
+}
+
+bool cmQtAutoGeneratorMocUic::ParallelMocIncluded(
+ std::string const& sourceFile)
+{
+ std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ return (MocIncludedFiles_.find(sourceFile) != MocIncludedFiles_.end());
+}
+
+void cmQtAutoGeneratorMocUic::ParallelMocAutoRegister(
+ std::string const& mocFile)
+{
+ std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ MocAutoFiles_.emplace(mocFile);
+}
+
+void cmQtAutoGeneratorMocUic::ParallelMocAutoUpdated()
+{
+ std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ MocAutoFileUpdated_ = true;
+}
+
+void cmQtAutoGeneratorMocUic::MocGenerateCompilation()
+{
+ std::lock_guard<std::mutex> mocLock(JobsMutex_);
+ if (!JobError_ && Moc().Enabled) {
+ // Write mocs compilation build file
+ {
+ // Compose mocs compilation file content
+ std::string content =
+ "// This file is autogenerated. Changes will be overwritten.\n";
+ if (MocAutoFiles_.empty()) {
+ // Placeholder content
+ content += "// No files found that require moc or the moc files are "
+ "included\n";
+ content += "enum some_compilers { need_more_than_nothing };\n";
+ } else {
+ // Valid content
+ char const sbeg = Base().MultiConfig ? '<' : '"';
+ char const send = Base().MultiConfig ? '>' : '"';
+ for (std::string const& mocfile : MocAutoFiles_) {
+ content += "#include ";
+ content += sbeg;
+ content += mocfile;
+ content += send;
+ content += '\n';
+ }
+ }
+
+ std::string const& compAbs = Moc().CompFileAbs;
+ if (FileSys().FileDiffers(compAbs, content)) {
+ // Actually write mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::MOC, "Generating MOC compilation " + compAbs);
+ }
+ if (!FileSys().FileWrite(GeneratorT::MOC, compAbs, content)) {
+ Log().ErrorFile(GeneratorT::MOC, compAbs,
+ "mocs compilation file writing failed");
+ RegisterJobError();
+ return;
+ }
+ } else if (MocAutoFileUpdated_) {
+ // Only touch mocs compilation file
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::MOC, "Touching mocs compilation " + compAbs);
+ }
+ FileSys().Touch(compAbs);
+ }
+ }
+ // Write mocs compilation wrapper file
+ if (Base().MultiConfig) {
+ }
+ }
+}
diff --git a/Source/cmQtAutoGeneratorMocUic.h b/Source/cmQtAutoGeneratorMocUic.h
new file mode 100644
index 000000000..696d5bdb2
--- /dev/null
+++ b/Source/cmQtAutoGeneratorMocUic.h
@@ -0,0 +1,438 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmQtAutoGeneratorMocUic_h
+#define cmQtAutoGeneratorMocUic_h
+
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cmFilePathChecksum.h"
+#include "cmQtAutoGen.h"
+#include "cmQtAutoGenerator.h"
+#include "cmUVHandlePtr.h"
+#include "cm_uv.h"
+#include "cmsys/RegularExpression.hxx"
+
+#include <algorithm>
+#include <condition_variable>
+#include <cstddef>
+#include <deque>
+#include <map>
+#include <memory> // IWYU pragma: keep
+#include <mutex>
+#include <set>
+#include <string>
+#include <thread>
+#include <vector>
+
+class cmMakefile;
+
+// @brief AUTOMOC and AUTOUIC generator
+class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator
+{
+ CM_DISABLE_COPY(cmQtAutoGeneratorMocUic)
+public:
+ cmQtAutoGeneratorMocUic();
+ ~cmQtAutoGeneratorMocUic() override;
+
+public:
+ // -- Types
+ class WorkerT;
+
+ /// @brief Search key plus regular expression pair
+ ///
+ struct KeyExpT
+ {
+ KeyExpT() = default;
+
+ KeyExpT(const char* key, const char* exp)
+ : Key(key)
+ , Exp(exp)
+ {
+ }
+
+ KeyExpT(std::string const& key, std::string const& exp)
+ : Key(key)
+ , Exp(exp)
+ {
+ }
+
+ std::string Key;
+ cmsys::RegularExpression Exp;
+ };
+
+ /// @brief Common settings
+ ///
+ class BaseSettingsT
+ {
+ CM_DISABLE_COPY(BaseSettingsT)
+ public:
+ // -- Volatile methods
+ BaseSettingsT(FileSystem* fileSystem)
+ : MultiConfig(false)
+ , IncludeProjectDirsBefore(false)
+ , QtVersionMajor(4)
+ , NumThreads(1)
+ , FileSys(fileSystem)
+ {
+ }
+
+ // -- Const methods
+ std::string AbsoluteBuildPath(std::string const& relativePath) const;
+ bool FindHeader(std::string& header,
+ std::string const& testBasePath) const;
+
+ // -- Attributes
+ // - Config
+ bool MultiConfig;
+ bool IncludeProjectDirsBefore;
+ unsigned int QtVersionMajor;
+ unsigned int NumThreads;
+ // - Directories
+ std::string ProjectSourceDir;
+ std::string ProjectBinaryDir;
+ std::string CurrentSourceDir;
+ std::string CurrentBinaryDir;
+ std::string AutogenBuildDir;
+ std::string AutogenIncludeDir;
+ // - Files
+ cmFilePathChecksum FilePathChecksum;
+ std::vector<std::string> HeaderExtensions;
+ // - File system
+ FileSystem* FileSys;
+ };
+
+ /// @brief Moc settings
+ ///
+ class MocSettingsT
+ {
+ CM_DISABLE_COPY(MocSettingsT)
+ public:
+ MocSettingsT(FileSystem* fileSys)
+ : FileSys(fileSys)
+ {
+ }
+
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+ std::string FindMacro(std::string const& content) const;
+ std::string MacrosString() const;
+ std::string FindIncludedFile(std::string const& sourcePath,
+ std::string const& includeString) const;
+ void FindDependencies(std::string const& content,
+ std::set<std::string>& depends) const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ bool RelaxedMode = false;
+ std::string Executable;
+ std::string CompFileAbs;
+ std::string PredefsFileRel;
+ std::string PredefsFileAbs;
+ std::set<std::string> SkipList;
+ std::vector<std::string> IncludePaths;
+ std::vector<std::string> Includes;
+ std::vector<std::string> Definitions;
+ std::vector<std::string> Options;
+ std::vector<std::string> AllOptions;
+ std::vector<std::string> PredefsCmd;
+ std::vector<KeyExpT> DependFilters;
+ std::vector<KeyExpT> MacroFilters;
+ cmsys::RegularExpression RegExpInclude;
+ // - File system
+ FileSystem* FileSys;
+ };
+
+ /// @brief Uic settings
+ ///
+ class UicSettingsT
+ {
+ CM_DISABLE_COPY(UicSettingsT)
+ public:
+ UicSettingsT() = default;
+ // -- Const methods
+ bool skipped(std::string const& fileName) const;
+
+ // -- Attributes
+ bool Enabled = false;
+ bool SettingsChanged = false;
+ std::string Executable;
+ std::set<std::string> SkipList;
+ std::vector<std::string> TargetOptions;
+ std::map<std::string, std::vector<std::string>> Options;
+ std::vector<std::string> SearchPaths;
+ cmsys::RegularExpression RegExpInclude;
+ };
+
+ /// @brief Abstract job class for threaded processing
+ ///
+ class JobT
+ {
+ CM_DISABLE_COPY(JobT)
+ public:
+ JobT() = default;
+ virtual ~JobT() = default;
+ // -- Abstract processing interface
+ virtual void Process(WorkerT& wrk) = 0;
+ };
+
+ /// @brief Deleter for classes derived from Job
+ ///
+ struct JobDeleterT
+ {
+ void operator()(JobT* job);
+ };
+
+ // Job management types
+ typedef std::unique_ptr<JobT, JobDeleterT> JobHandleT;
+ typedef std::deque<JobHandleT> JobQueueT;
+
+ /// @brief Parse source job
+ ///
+ class JobParseT : public JobT
+ {
+ public:
+ JobParseT(std::string&& fileName, bool moc, bool uic, bool header = false)
+ : FileName(std::move(fileName))
+ , AutoMoc(moc)
+ , AutoUic(uic)
+ , Header(header)
+ {
+ }
+
+ private:
+ struct MetaT
+ {
+ std::string Content;
+ std::string FileDir;
+ std::string FileBase;
+ };
+
+ void Process(WorkerT& wrk) override;
+ bool ParseMocSource(WorkerT& wrk, MetaT const& meta);
+ bool ParseMocHeader(WorkerT& wrk, MetaT const& meta);
+ std::string MocStringHeaders(WorkerT& wrk,
+ std::string const& fileBase) const;
+ std::string MocFindIncludedHeader(WorkerT& wrk,
+ std::string const& includerDir,
+ std::string const& includeBase);
+ bool ParseUic(WorkerT& wrk, MetaT const& meta);
+ bool ParseUicInclude(WorkerT& wrk, MetaT const& meta,
+ std::string&& includeString);
+ std::string UicFindIncludedFile(WorkerT& wrk, MetaT const& meta,
+ std::string const& includeString);
+
+ private:
+ std::string FileName;
+ bool AutoMoc = false;
+ bool AutoUic = false;
+ bool Header = false;
+ };
+
+ /// @brief Generate moc_predefs
+ ///
+ class JobMocPredefsT : public JobT
+ {
+ private:
+ void Process(WorkerT& wrk) override;
+ };
+
+ /// @brief Moc a file job
+ ///
+ class JobMocT : public JobT
+ {
+ public:
+ JobMocT(std::string&& sourceFile, std::string const& includerFile,
+ std::string&& includeString)
+ : SourceFile(std::move(sourceFile))
+ , IncluderFile(includerFile)
+ , IncludeString(std::move(includeString))
+ {
+ }
+
+ void FindDependencies(WorkerT& wrk, std::string const& content);
+
+ private:
+ void Process(WorkerT& wrk) override;
+ bool UpdateRequired(WorkerT& wrk);
+ void GenerateMoc(WorkerT& wrk);
+
+ public:
+ std::string SourceFile;
+ std::string IncluderFile;
+ std::string IncludeString;
+ std::string BuildFile;
+ bool DependsValid = false;
+ std::set<std::string> Depends;
+ };
+
+ /// @brief Uic a file job
+ ///
+ class JobUicT : public JobT
+ {
+ public:
+ JobUicT(std::string&& sourceFile, std::string const& includerFile,
+ std::string&& includeString)
+ : SourceFile(std::move(sourceFile))
+ , IncluderFile(includerFile)
+ , IncludeString(std::move(includeString))
+ {
+ }
+
+ private:
+ void Process(WorkerT& wrk) override;
+ bool UpdateRequired(WorkerT& wrk);
+ void GenerateUic(WorkerT& wrk);
+
+ public:
+ std::string SourceFile;
+ std::string IncluderFile;
+ std::string IncludeString;
+ std::string BuildFile;
+ };
+
+ /// @brief Worker Thread
+ ///
+ class WorkerT
+ {
+ CM_DISABLE_COPY(WorkerT)
+ public:
+ WorkerT(cmQtAutoGeneratorMocUic* gen, uv_loop_t* uvLoop);
+ ~WorkerT();
+
+ // -- Const accessors
+ cmQtAutoGeneratorMocUic& Gen() const { return *Gen_; }
+ Logger& Log() const { return Gen_->Log(); }
+ FileSystem& FileSys() const { return Gen_->FileSys(); }
+ const BaseSettingsT& Base() const { return Gen_->Base(); }
+ const MocSettingsT& Moc() const { return Gen_->Moc(); }
+ const UicSettingsT& Uic() const { return Gen_->Uic(); }
+
+ // -- Log info
+ void LogInfo(GeneratorT genType, std::string const& message) const;
+ // -- Log warning
+ void LogWarning(GeneratorT genType, std::string const& message) const;
+ void LogFileWarning(GeneratorT genType, std::string const& filename,
+ std::string const& message) const;
+ // -- Log error
+ void LogError(GeneratorT genType, std::string const& message) const;
+ void LogFileError(GeneratorT genType, std::string const& filename,
+ std::string const& message) const;
+ void LogCommandError(GeneratorT genType, std::string const& message,
+ std::vector<std::string> const& command,
+ std::string const& output) const;
+
+ // -- External processes
+ /// @brief Verbose logging version
+ bool RunProcess(GeneratorT genType, ProcessResultT& result,
+ std::vector<std::string> const& command);
+
+ private:
+ /// @brief Thread main loop
+ void Loop();
+
+ // -- Libuv callbacks
+ static void UVProcessStart(uv_async_t* handle);
+ void UVProcessFinished();
+
+ private:
+ // -- Generator
+ cmQtAutoGeneratorMocUic* Gen_;
+ // -- Job handle
+ JobHandleT JobHandle_;
+ // -- Process management
+ std::mutex ProcessMutex_;
+ cm::uv_async_ptr ProcessRequest_;
+ std::condition_variable ProcessCondition_;
+ std::unique_ptr<ReadOnlyProcessT> Process_;
+ // -- System thread
+ std::thread Thread_;
+ };
+
+ /// @brief Processing stage
+ enum class StageT
+ {
+ SETTINGS_READ,
+ CREATE_DIRECTORIES,
+ PARSE_SOURCES,
+ PARSE_HEADERS,
+ MOC_PREDEFS,
+ MOC_PROCESS,
+ MOCS_COMPILATION,
+ UIC_PROCESS,
+ SETTINGS_WRITE,
+ FINISH,
+ END
+ };
+
+ // -- Const settings interface
+ const BaseSettingsT& Base() const { return this->Base_; }
+ const MocSettingsT& Moc() const { return this->Moc_; }
+ const UicSettingsT& Uic() const { return this->Uic_; }
+
+ // -- Worker thread interface
+ void WorkerSwapJob(JobHandleT& jobHandle);
+ // -- Parallel job processing interface
+ void ParallelRegisterJobError();
+ bool ParallelJobPushMoc(JobHandleT& jobHandle);
+ bool ParallelJobPushUic(JobHandleT& jobHandle);
+ bool ParallelMocIncluded(std::string const& sourceFile);
+ void ParallelMocAutoRegister(std::string const& mocFile);
+ void ParallelMocAutoUpdated();
+
+private:
+ // -- Abstract processing interface
+ bool Init(cmMakefile* makefile) override;
+ bool Process() override;
+ // -- Process stage
+ static void UVPollStage(uv_async_t* handle);
+ void PollStage();
+ void SetStage(StageT stage);
+ // -- Settings file
+ void SettingsFileRead();
+ void SettingsFileWrite();
+ // -- Thread processing
+ bool ThreadsStartJobs(JobQueueT& queue);
+ bool ThreadsJobsDone();
+ void ThreadsStop();
+ void RegisterJobError();
+ // -- Generation
+ void CreateDirectories();
+ void MocGenerateCompilation();
+
+private:
+ // -- Settings
+ BaseSettingsT Base_;
+ MocSettingsT Moc_;
+ UicSettingsT Uic_;
+ // -- Progress
+ StageT Stage_;
+ // -- Job queues
+ std::mutex JobsMutex_;
+ struct
+ {
+ JobQueueT Sources;
+ JobQueueT Headers;
+ JobQueueT MocPredefs;
+ JobQueueT Moc;
+ JobQueueT Uic;
+ } JobQueues_;
+ JobQueueT JobQueue_;
+ std::size_t volatile JobsRemain_;
+ bool volatile JobError_;
+ bool volatile JobThreadsAbort_;
+ std::condition_variable JobsConditionRead_;
+ // -- Moc meta
+ std::set<std::string> MocIncludedStrings_;
+ std::set<std::string> MocIncludedFiles_;
+ std::set<std::string> MocAutoFiles_;
+ bool volatile MocAutoFileUpdated_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsStringMoc_;
+ std::string SettingsStringUic_;
+ // -- Threads and loops
+ std::vector<std::unique_ptr<WorkerT>> Workers_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx
new file mode 100644
index 000000000..2bf00f7aa
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.cxx
@@ -0,0 +1,638 @@
+/* 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 "cmSystemTools.h"
+#include "cmUVHandlePtr.h"
+
+#include <functional>
+
+// -- Class methods
+
+cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc()
+ : MultiConfig_(false)
+ , SettingsChanged_(false)
+ , Stage_(StageT::SETTINGS_READ)
+ , Error_(false)
+ , Generate_(false)
+ , BuildFileChanged_(false)
+{
+ // Initialize libuv asynchronous iteration request
+ UVRequest().init(*UVLoop(), &cmQtAutoGeneratorRcc::UVPollStage, this);
+}
+
+cmQtAutoGeneratorRcc::~cmQtAutoGeneratorRcc()
+{
+}
+
+bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile)
+{
+ // -- Utility lambdas
+ auto InfoGet = [makefile](std::string const& key) {
+ return makefile->GetSafeDefinition(key);
+ };
+ auto InfoGetList =
+ [makefile](std::string const& key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list);
+ return list;
+ };
+ auto InfoGetConfig = [makefile,
+ this](std::string const& key) -> std::string {
+ const char* valueConf = nullptr;
+ {
+ std::string keyConf = key;
+ keyConf += '_';
+ keyConf += InfoConfig();
+ valueConf = makefile->GetDefinition(keyConf);
+ }
+ if (valueConf == nullptr) {
+ valueConf = makefile->GetSafeDefinition(key);
+ }
+ return std::string(valueConf);
+ };
+ auto InfoGetConfigList =
+ [&InfoGetConfig](std::string const& key) -> std::vector<std::string> {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(InfoGetConfig(key), list);
+ return list;
+ };
+
+ // -- Read info file
+ if (!makefile->ReadListFile(InfoFile().c_str())) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "File processing failed");
+ return false;
+ }
+
+ // - Configurations
+ MultiConfig_ = makefile->IsOn("ARCC_MULTI_CONFIG");
+
+ // - Directories
+ AutogenBuildDir_ = InfoGet("ARCC_BUILD_DIR");
+ if (AutogenBuildDir_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Build directory empty");
+ return false;
+ }
+
+ IncludeDir_ = InfoGetConfig("ARCC_INCLUDE_DIR");
+ if (IncludeDir_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Include directory empty");
+ return false;
+ }
+
+ // - Rcc executable
+ RccExecutable_ = InfoGet("ARCC_RCC_EXECUTABLE");
+ RccListOptions_ = InfoGetList("ARCC_RCC_LIST_OPTIONS");
+
+ // - Job
+ QrcFile_ = InfoGet("ARCC_SOURCE");
+ QrcFileName_ = cmSystemTools::GetFilenameName(QrcFile_);
+ QrcFileDir_ = cmSystemTools::GetFilenamePath(QrcFile_);
+ RccPathChecksum_ = InfoGet("ARCC_OUTPUT_CHECKSUM");
+ RccFileName_ = InfoGet("ARCC_OUTPUT_NAME");
+ Options_ = InfoGetConfigList("ARCC_OPTIONS");
+ Inputs_ = InfoGetList("ARCC_INPUTS");
+
+ // - Settings file
+ SettingsFile_ = InfoGetConfig("ARCC_SETTINGS_FILE");
+
+ // - Validity checks
+ if (SettingsFile_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "Settings file name missing");
+ return false;
+ }
+ if (AutogenBuildDir_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(),
+ "Autogen build directory missing");
+ return false;
+ }
+ if (RccExecutable_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc executable missing");
+ return false;
+ }
+ if (QrcFile_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc input file missing");
+ return false;
+ }
+ if (RccFileName_.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, InfoFile(), "rcc output file missing");
+ return false;
+ }
+
+ // Init derived information
+ // ------------------------
+
+ RccFilePublic_ = AutogenBuildDir_;
+ RccFilePublic_ += '/';
+ RccFilePublic_ += RccPathChecksum_;
+ RccFilePublic_ += '/';
+ RccFilePublic_ += RccFileName_;
+
+ // Compute rcc output file name
+ if (IsMultiConfig()) {
+ RccFileOutput_ = AutogenBuildDir_;
+ RccFileOutput_ += '/';
+ RccFileOutput_ += IncludeDir_;
+ RccFileOutput_ += '/';
+ RccFileOutput_ += MultiConfigOutput();
+ } else {
+ RccFileOutput_ = RccFilePublic_;
+ }
+
+ return true;
+}
+
+bool cmQtAutoGeneratorRcc::Process()
+{
+ // Run libuv event loop
+ UVRequest().send();
+ if (uv_run(UVLoop(), UV_RUN_DEFAULT) == 0) {
+ if (Error_) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ return true;
+}
+
+void cmQtAutoGeneratorRcc::UVPollStage(uv_async_t* handle)
+{
+ reinterpret_cast<cmQtAutoGeneratorRcc*>(handle->data)->PollStage();
+}
+
+void cmQtAutoGeneratorRcc::PollStage()
+{
+ switch (Stage_) {
+ // -- Initialize
+ case StageT::SETTINGS_READ:
+ SettingsFileRead();
+ SetStage(StageT::TEST_QRC_RCC_FILES);
+ break;
+
+ // -- Change detection
+ case StageT::TEST_QRC_RCC_FILES:
+ if (TestQrcRccFiles()) {
+ SetStage(StageT::GENERATE);
+ } else {
+ SetStage(StageT::TEST_RESOURCES_READ);
+ }
+ break;
+ case StageT::TEST_RESOURCES_READ:
+ if (TestResourcesRead()) {
+ SetStage(StageT::TEST_RESOURCES);
+ }
+ break;
+ case StageT::TEST_RESOURCES:
+ if (TestResources()) {
+ SetStage(StageT::GENERATE);
+ } else {
+ SetStage(StageT::TEST_INFO_FILE);
+ }
+ break;
+ case StageT::TEST_INFO_FILE:
+ TestInfoFile();
+ SetStage(StageT::GENERATE_WRAPPER);
+ break;
+
+ // -- Generation
+ case StageT::GENERATE:
+ GenerateParentDir();
+ SetStage(StageT::GENERATE_RCC);
+ break;
+ case StageT::GENERATE_RCC:
+ if (GenerateRcc()) {
+ SetStage(StageT::GENERATE_WRAPPER);
+ }
+ break;
+ case StageT::GENERATE_WRAPPER:
+ GenerateWrapper();
+ SetStage(StageT::SETTINGS_WRITE);
+ break;
+
+ // -- Finalize
+ case StageT::SETTINGS_WRITE:
+ SettingsFileWrite();
+ SetStage(StageT::FINISH);
+ break;
+ case StageT::FINISH:
+ // Clear all libuv handles
+ UVRequest().reset();
+ // Set highest END stage manually
+ Stage_ = StageT::END;
+ break;
+ case StageT::END:
+ break;
+ }
+}
+
+void cmQtAutoGeneratorRcc::SetStage(StageT stage)
+{
+ if (Error_) {
+ stage = StageT::FINISH;
+ }
+ // Only allow to increase the stage
+ if (Stage_ < stage) {
+ Stage_ = stage;
+ UVRequest().send();
+ }
+}
+
+std::string cmQtAutoGeneratorRcc::MultiConfigOutput() const
+{
+ static std::string const suffix = "_CMAKE_";
+ std::string res;
+ res += RccPathChecksum_;
+ res += '/';
+ res += AppendFilenameSuffix(RccFileName_, suffix);
+ return res;
+}
+
+void cmQtAutoGeneratorRcc::SettingsFileRead()
+{
+ // Compose current settings strings
+ {
+ cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
+ std::string const sep(" ~~~ ");
+ {
+ std::string str;
+ str += RccExecutable_;
+ str += sep;
+ str += cmJoin(RccListOptions_, ";");
+ str += sep;
+ str += QrcFile_;
+ str += sep;
+ str += RccPathChecksum_;
+ str += sep;
+ str += RccFileName_;
+ str += sep;
+ str += cmJoin(Options_, ";");
+ str += sep;
+ str += cmJoin(Inputs_, ";");
+ str += sep;
+ SettingsString_ = crypt.HashString(str);
+ }
+ }
+
+ // Read old settings
+ {
+ std::string content;
+ if (FileSys().FileRead(content, SettingsFile_)) {
+ SettingsChanged_ = (SettingsString_ != SettingsFind(content, "rcc"));
+ // 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 (SettingsChanged_) {
+ FileSys().FileRemove(SettingsFile_);
+ }
+ } else {
+ SettingsChanged_ = true;
+ }
+ }
+}
+
+void cmQtAutoGeneratorRcc::SettingsFileWrite()
+{
+ // Only write if any setting changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::RCC,
+ "Writing settings file " + Quoted(SettingsFile_));
+ }
+ // Write settings file
+ std::string content = "rcc:";
+ content += SettingsString_;
+ content += '\n';
+ if (!FileSys().FileWrite(GeneratorT::RCC, SettingsFile_, content)) {
+ Log().ErrorFile(GeneratorT::RCC, SettingsFile_,
+ "Settings file writing failed");
+ // Remove old settings file to trigger a full rebuild on the next run
+ FileSys().FileRemove(SettingsFile_);
+ Error_ = true;
+ }
+ }
+}
+
+bool cmQtAutoGeneratorRcc::TestQrcRccFiles()
+{
+ // Do basic checks if rcc generation is required
+
+ // Test if the rcc output file exists
+ if (!FileSys().FileExists(RccFileOutput_)) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from its source file ";
+ reason += Quoted(QrcFile_);
+ reason += " because it doesn't exist";
+ Log().Info(GeneratorT::RCC, reason);
+ }
+ Generate_ = true;
+ return Generate_;
+ }
+
+ // Test if the settings changed
+ if (SettingsChanged_) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from ";
+ reason += Quoted(QrcFile_);
+ reason += " because the RCC settings changed";
+ Log().Info(GeneratorT::RCC, reason);
+ }
+ Generate_ = true;
+ return Generate_;
+ }
+
+ // Test if the rcc output file is older than the .qrc file
+ {
+ bool isOlder = false;
+ {
+ std::string error;
+ isOlder = FileSys().FileIsOlderThan(RccFileOutput_, QrcFile_, &error);
+ if (!error.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
+ Error_ = true;
+ }
+ }
+ if (isOlder) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " because it is older than ";
+ reason += Quoted(QrcFile_);
+ Log().Info(GeneratorT::RCC, reason);
+ }
+ Generate_ = true;
+ }
+ }
+
+ return Generate_;
+}
+
+bool cmQtAutoGeneratorRcc::TestResourcesRead()
+{
+ if (!Inputs_.empty()) {
+ // Inputs are known already
+ return true;
+ }
+
+ if (!RccListOptions_.empty()) {
+ // Start a rcc list process and parse the output
+ if (Process_) {
+ // Process is running already
+ if (Process_->IsFinished()) {
+ // Process is finished
+ if (!ProcessResult_.error()) {
+ // Process success
+ std::string parseError;
+ if (!RccListParseOutput(ProcessResult_.StdOut, ProcessResult_.StdErr,
+ Inputs_, parseError)) {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, parseError);
+ Error_ = true;
+ }
+ } else {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_,
+ ProcessResult_.ErrorMessage);
+ Error_ = true;
+ }
+ // Clean up
+ Process_.reset();
+ ProcessResult_.reset();
+ } else {
+ // Process is not finished, yet.
+ return false;
+ }
+ } else {
+ // Start a new process
+ // rcc prints relative entry paths when started in the directory of the
+ // qrc file with a pathless qrc file name argument.
+ // This is important because on Windows absolute paths returned by rcc
+ // might contain bad multibyte characters when the qrc file path
+ // contains non-ASCII pcharacters.
+ std::vector<std::string> cmd;
+ cmd.push_back(RccExecutable_);
+ cmd.insert(cmd.end(), RccListOptions_.begin(), RccListOptions_.end());
+ cmd.push_back(QrcFileName_);
+ // We're done here if the process fails to start
+ return !StartProcess(QrcFileDir_, cmd, false);
+ }
+ } else {
+ // rcc does not support the --list command.
+ // Read the qrc file content and parse it.
+ std::string qrcContent;
+ if (FileSys().FileRead(GeneratorT::RCC, qrcContent, QrcFile_)) {
+ RccListParseContent(qrcContent, Inputs_);
+ }
+ }
+
+ if (!Inputs_.empty()) {
+ // Convert relative paths to absolute paths
+ RccListConvertFullPath(QrcFileDir_, Inputs_);
+ }
+
+ return true;
+}
+
+bool cmQtAutoGeneratorRcc::TestResources()
+{
+ if (Inputs_.empty()) {
+ return true;
+ }
+ {
+ std::string error;
+ for (std::string const& resFile : Inputs_) {
+ // Check if the resource file exists
+ if (!FileSys().FileExists(resFile)) {
+ error = "Could not find the resource file\n ";
+ error += Quoted(resFile);
+ error += '\n';
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
+ Error_ = true;
+ break;
+ }
+ // Check if the resource file is newer than the build file
+ if (FileSys().FileIsOlderThan(RccFileOutput_, resFile, &error)) {
+ if (Log().Verbose()) {
+ std::string reason = "Generating ";
+ reason += Quoted(RccFileOutput_);
+ reason += " from ";
+ reason += Quoted(QrcFile_);
+ reason += " because it is older than ";
+ reason += Quoted(resFile);
+ Log().Info(GeneratorT::RCC, reason);
+ }
+ Generate_ = true;
+ break;
+ }
+ // Print error and break on demand
+ if (!error.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
+ Error_ = true;
+ break;
+ }
+ }
+ }
+
+ return Generate_;
+}
+
+void cmQtAutoGeneratorRcc::TestInfoFile()
+{
+ // Test if the rcc output file is older than the info file
+ {
+ bool isOlder = false;
+ {
+ std::string error;
+ isOlder = FileSys().FileIsOlderThan(RccFileOutput_, InfoFile(), &error);
+ if (!error.empty()) {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, error);
+ Error_ = true;
+ }
+ }
+ if (isOlder) {
+ if (Log().Verbose()) {
+ std::string reason = "Touching ";
+ reason += Quoted(RccFileOutput_);
+ reason += " because it is older than ";
+ reason += Quoted(InfoFile());
+ Log().Info(GeneratorT::RCC, reason);
+ }
+ // Touch build file
+ FileSys().Touch(RccFileOutput_);
+ BuildFileChanged_ = true;
+ }
+ }
+}
+
+void cmQtAutoGeneratorRcc::GenerateParentDir()
+{
+ // Make sure the parent directory exists
+ if (!FileSys().MakeParentDirectory(GeneratorT::RCC, RccFileOutput_)) {
+ Error_ = true;
+ }
+}
+
+/**
+ * @return True when finished
+ */
+bool cmQtAutoGeneratorRcc::GenerateRcc()
+{
+ if (!Generate_) {
+ // Nothing to do
+ return true;
+ }
+
+ if (Process_) {
+ // Process is running already
+ if (Process_->IsFinished()) {
+ // Process is finished
+ if (!ProcessResult_.error()) {
+ // Process success
+ BuildFileChanged_ = true;
+ } else {
+ // Process failed
+ {
+ std::string emsg = "The rcc process failed to compile\n ";
+ emsg += Quoted(QrcFile_);
+ emsg += "\ninto\n ";
+ emsg += Quoted(RccFileOutput_);
+ if (ProcessResult_.error()) {
+ emsg += "\n";
+ emsg += ProcessResult_.ErrorMessage;
+ }
+ Log().ErrorCommand(GeneratorT::RCC, emsg, Process_->Setup().Command,
+ ProcessResult_.StdOut);
+ }
+ FileSys().FileRemove(RccFileOutput_);
+ Error_ = true;
+ }
+ // Clean up
+ Process_.reset();
+ ProcessResult_.reset();
+ } else {
+ // Process is not finished, yet.
+ return false;
+ }
+ } else {
+ // Start a rcc process
+ std::vector<std::string> cmd;
+ cmd.push_back(RccExecutable_);
+ cmd.insert(cmd.end(), Options_.begin(), Options_.end());
+ cmd.push_back("-o");
+ cmd.push_back(RccFileOutput_);
+ cmd.push_back(QrcFile_);
+ // We're done here if the process fails to start
+ return !StartProcess(AutogenBuildDir_, cmd, true);
+ }
+
+ return true;
+}
+
+void cmQtAutoGeneratorRcc::GenerateWrapper()
+{
+ // Generate a wrapper source file on demand
+ if (IsMultiConfig()) {
+ // Wrapper file content
+ std::string content;
+ content += "// This is an autogenerated configuration wrapper file.\n";
+ content += "// Changes will be overwritten.\n";
+ content += "#include <";
+ content += MultiConfigOutput();
+ content += ">\n";
+
+ // Write content to file
+ if (FileSys().FileDiffers(RccFilePublic_, content)) {
+ // Write new wrapper file
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::RCC,
+ "Generating RCC wrapper file " + RccFilePublic_);
+ }
+ if (!FileSys().FileWrite(GeneratorT::RCC, RccFilePublic_, content)) {
+ Log().ErrorFile(GeneratorT::RCC, RccFilePublic_,
+ "RCC wrapper file writing failed");
+ Error_ = true;
+ }
+ } else if (BuildFileChanged_) {
+ // Just touch the wrapper file
+ if (Log().Verbose()) {
+ Log().Info(GeneratorT::RCC,
+ "Touching RCC wrapper file " + RccFilePublic_);
+ }
+ FileSys().Touch(RccFilePublic_);
+ }
+ }
+}
+
+bool cmQtAutoGeneratorRcc::StartProcess(
+ std::string const& workingDirectory, std::vector<std::string> const& command,
+ bool mergedOutput)
+{
+ // Log command
+ if (Log().Verbose()) {
+ std::string msg = "Running command:\n";
+ msg += QuotedCommand(command);
+ msg += '\n';
+ Log().Info(GeneratorT::RCC, msg);
+ }
+
+ // Create process handler
+ Process_ = cm::make_unique<ReadOnlyProcessT>();
+ Process_->setup(&ProcessResult_, mergedOutput, command, workingDirectory);
+ // Start process
+ if (!Process_->start(UVLoop(),
+ std::bind(&cm::uv_async_ptr::send, &UVRequest()))) {
+ Log().ErrorFile(GeneratorT::RCC, QrcFile_, ProcessResult_.ErrorMessage);
+ Error_ = true;
+ // Clean up
+ Process_.reset();
+ ProcessResult_.reset();
+ return false;
+ }
+ return true;
+}
diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h
new file mode 100644
index 000000000..55e099811
--- /dev/null
+++ b/Source/cmQtAutoGeneratorRcc.h
@@ -0,0 +1,103 @@
+/* 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 "cmQtAutoGenerator.h"
+#include "cm_uv.h"
+
+#include <string>
+#include <vector>
+
+class cmMakefile;
+
+// @brief AUTORCC generator
+class cmQtAutoGeneratorRcc : public cmQtAutoGenerator
+{
+ CM_DISABLE_COPY(cmQtAutoGeneratorRcc)
+public:
+ cmQtAutoGeneratorRcc();
+ ~cmQtAutoGeneratorRcc() override;
+
+private:
+ // -- Types
+
+ /// @brief Processing stage
+ enum class StageT : unsigned char
+ {
+ SETTINGS_READ,
+ TEST_QRC_RCC_FILES,
+ TEST_RESOURCES_READ,
+ TEST_RESOURCES,
+ TEST_INFO_FILE,
+ GENERATE,
+ GENERATE_RCC,
+ GENERATE_WRAPPER,
+ SETTINGS_WRITE,
+ FINISH,
+ END
+ };
+
+ // -- Abstract processing interface
+ bool Init(cmMakefile* makefile) override;
+ bool Process() override;
+ // -- Process stage
+ static void UVPollStage(uv_async_t* handle);
+ void PollStage();
+ void SetStage(StageT stage);
+ // -- Settings file
+ void SettingsFileRead();
+ void SettingsFileWrite();
+ // -- Tests
+ bool TestQrcRccFiles();
+ bool TestResourcesRead();
+ bool TestResources();
+ void TestInfoFile();
+ // -- Generation
+ void GenerateParentDir();
+ bool GenerateRcc();
+ void GenerateWrapper();
+
+ // -- Utility
+ bool IsMultiConfig() const { return MultiConfig_; }
+ std::string MultiConfigOutput() const;
+ bool StartProcess(std::string const& workingDirectory,
+ std::vector<std::string> const& command,
+ bool mergedOutput);
+
+private:
+ // -- Config settings
+ bool MultiConfig_;
+ // -- Directories
+ std::string AutogenBuildDir_;
+ std::string IncludeDir_;
+ // -- Qt environment
+ std::string RccExecutable_;
+ std::vector<std::string> RccListOptions_;
+ // -- Job
+ std::string QrcFile_;
+ std::string QrcFileName_;
+ std::string QrcFileDir_;
+ std::string RccPathChecksum_;
+ std::string RccFileName_;
+ std::string RccFileOutput_;
+ std::string RccFilePublic_;
+ std::vector<std::string> Options_;
+ std::vector<std::string> Inputs_;
+ // -- Subprocess
+ ProcessResultT ProcessResult_;
+ std::unique_ptr<ReadOnlyProcessT> Process_;
+ // -- Settings file
+ std::string SettingsFile_;
+ std::string SettingsString_;
+ bool SettingsChanged_;
+ // -- libuv loop
+ StageT Stage_;
+ bool Error_;
+ bool Generate_;
+ bool BuildFileChanged_;
+};
+
+#endif
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
deleted file mode 100644
index f91ebb23e..000000000
--- a/Source/cmQtAutoGenerators.cxx
+++ /dev/null
@@ -1,2341 +0,0 @@
-/* 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 "cmsys/FStream.hxx"
-#include "cmsys/Terminal.h"
-#include <algorithm>
-#include <array>
-#include <list>
-#include <memory>
-#include <sstream>
-#include <string.h>
-#include <utility>
-
-#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"
-
-#if defined(__APPLE__)
-#include <unistd.h>
-#endif
-
-// -- Static variables
-
-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));
- if (!res.empty()) {
- res += '/';
- }
- 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) {
- if (length > 0) {
- 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 {
- // Readable but empty file
- content.clear();
- success = true;
- }
- } 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)
-{
- return (std::find(list.begin(), list.end(), entry) != list.end());
-}
-
-// -- Class methods
-
-cmQtAutoGenerators::cmQtAutoGenerators()
- : MultiConfig(cmQtAutoGen::WRAP)
- , IncludeProjectDirsBefore(false)
- , Verbose(cmSystemTools::HasEnv("VERBOSE"))
- , ColorOutput(true)
- , 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]+"
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
- this->UicRegExpInclude.compile("[\n][ \t]*#[ \t]*include[ \t]+"
- "[\"<](([^ \">]+/)?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);
- // The OLD/WARN behavior for policy CMP0053 caused a speed regression.
- // https://gitlab.kitware.com/cmake/cmake/issues/17570
- makefile->SetPolicyVersion("3.9");
- 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)
-{
- // -- Meta
- this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
-
- // Utility lambdas
- auto InfoGet = [makefile](const char* key) {
- return makefile->GetSafeDefinition(key);
- };
- auto InfoGetBool = [makefile](const char* key) {
- return makefile->IsOn(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 InfoGetLists =
- [makefile](const char* key) -> std::vector<std::vector<std::string>> {
- std::vector<std::vector<std::string>> lists;
- {
- std::string const value = makefile->GetSafeDefinition(key);
- std::string::size_type pos = 0;
- while (pos < value.size()) {
- std::string::size_type next = value.find(cmQtAutoGen::listSep, pos);
- std::string::size_type length =
- (next != std::string::npos) ? next - pos : value.size() - pos;
- // Remove enclosing braces
- if (length >= 2) {
- std::string::const_iterator itBeg = value.begin() + (pos + 1);
- std::string::const_iterator itEnd = itBeg + (length - 2);
- {
- std::string subValue(itBeg, itEnd);
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(subValue, list);
- lists.push_back(std::move(list));
- }
- }
- pos += length;
- pos += cmQtAutoGen::listSep.size();
- }
- }
- return lists;
- };
- auto InfoGetConfig = [makefile, &config](const char* key) -> std::string {
- const char* valueConf = nullptr;
- {
- std::string keyConf = key;
- keyConf += '_';
- keyConf += config;
- 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
- 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,
- "File processing failed");
- return false;
- }
-
- // -- Meta
- this->MultiConfig = cmQtAutoGen::MultiConfigType(InfoGet("AM_MULTI_CONFIG"));
- this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX");
- if (this->ConfigSuffix.empty()) {
- this->ConfigSuffix = "_";
- this->ConfigSuffix += config;
- }
-
- // - Files and directories
- this->ProjectSourceDir = InfoGet("AM_CMAKE_SOURCE_DIR");
- this->ProjectBinaryDir = InfoGet("AM_CMAKE_BINARY_DIR");
- this->CurrentSourceDir = InfoGet("AM_CMAKE_CURRENT_SOURCE_DIR");
- this->CurrentBinaryDir = InfoGet("AM_CMAKE_CURRENT_BINARY_DIR");
- this->IncludeProjectDirsBefore =
- InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE");
- this->AutogenBuildDir = InfoGet("AM_BUILD_DIR");
- if (this->AutogenBuildDir.empty()) {
- this->LogFileError(cmQtAutoGen::GEN, this->InfoFile,
- "Autogen build directory missing");
- return false;
- }
-
- // - Qt environment
- this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR");
- this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR");
- 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()) {
- this->MocSkipList = InfoGetList("AM_MOC_SKIP");
- this->MocDefinitions = InfoGetConfigList("AM_MOC_DEFINITIONS");
-#ifdef _WIN32
- {
- std::string const win32("WIN32");
- if (!ListContains(this->MocDefinitions, win32)) {
- this->MocDefinitions.push_back(win32);
- }
- }
-#endif
- this->MocIncludePaths = InfoGetConfigList("AM_MOC_INCLUDES");
- this->MocOptions = InfoGetList("AM_MOC_OPTIONS");
- this->MocRelaxedMode = InfoGetBool("AM_MOC_RELAXED_MODE");
- {
- std::vector<std::string> const MocMacroNames =
- InfoGetList("AM_MOC_MACRO_NAMES");
- for (std::string const& item : MocMacroNames) {
- this->MocMacroFilters.emplace_back(
- item, ("[\n][ \t]*{?[ \t]*" + item).append("[^a-zA-Z0-9_]"));
- }
- }
- {
- std::vector<std::string> const mocDependFilters =
- InfoGetList("AM_MOC_DEPEND_FILTERS");
- // Insert Q_PLUGIN_METADATA dependency filter
- if (this->QtMajorVersion != "4") {
- this->MocDependFilterPush("Q_PLUGIN_METADATA",
- "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\("
- "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
- }
- // Insert user defined dependency filters
- if ((mocDependFilters.size() % 2) == 0) {
- for (std::vector<std::string>::const_iterator
- dit = mocDependFilters.begin(),
- ditEnd = mocDependFilters.end();
- dit != ditEnd; dit += 2) {
- if (!this->MocDependFilterPush(*dit, *(dit + 1))) {
- return false;
- }
- }
- } else {
- this->LogFileError(
- cmQtAutoGen::MOC, this->InfoFile,
- "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2");
- return false;
- }
- }
- this->MocPredefsCmd = InfoGetList("AM_MOC_PREDEFS_CMD");
- }
-
- // - Uic
- if (this->UicEnabled()) {
- this->UicSkipList = InfoGetList("AM_UIC_SKIP");
- this->UicSearchPaths = InfoGetList("AM_UIC_SEARCH_PATHS");
- this->UicTargetOptions = InfoGetConfigList("AM_UIC_TARGET_OPTIONS");
- {
- auto sources = InfoGetList("AM_UIC_OPTIONS_FILES");
- auto options = InfoGetLists("AM_UIC_OPTIONS_OPTIONS");
- // Compare list sizes
- if (sources.size() != options.size()) {
- std::ostringstream ost;
- ost << "files/options lists sizes missmatch (" << sources.size() << "/"
- << options.size() << ")";
- this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str());
- return false;
- }
- auto fitEnd = sources.cend();
- auto fit = sources.begin();
- auto oit = options.begin();
- while (fit != fitEnd) {
- this->UicOptions[*fit] = std::move(*oit);
- ++fit;
- ++oit;
- }
- }
- }
-
- // - 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
- auto AddJob = [this](std::map<std::string, SourceJob>& jobs,
- std::string&& sourceFile) {
- const bool moc = !this->MocSkip(sourceFile);
- const bool uic = !this->UicSkip(sourceFile);
- if (moc || uic) {
- SourceJob& job = jobs[std::move(sourceFile)];
- job.Moc = moc;
- job.Uic = uic;
- }
- };
-
- // Add header jobs
- for (std::string& hdr : InfoGetList("AM_HEADERS")) {
- AddJob(this->HeaderJobs, std::move(hdr));
- }
- // Add source jobs
- {
- std::vector<std::string> sources = InfoGetList("AM_SOURCES");
- // Add header(s) for the source file
- for (std::string const& src : sources) {
- const bool srcMoc = !this->MocSkip(src);
- const bool srcUic = !this->UicSkip(src);
- if (!srcMoc && !srcUic) {
- continue;
- }
- // Search for the default header file and a private header
- std::array<std::string, 2> headerBases;
- headerBases[0] = SubDirPrefix(src);
- headerBases[0] += cmSystemTools::GetFilenameWithoutLastExtension(src);
- headerBases[1] = headerBases[0];
- headerBases[1] += "_p";
- for (std::string const& headerBase : headerBases) {
- std::string header;
- if (this->FindHeader(header, headerBase)) {
- const bool moc = srcMoc && !this->MocSkip(header);
- const bool uic = srcUic && !this->UicSkip(header);
- if (moc || uic) {
- SourceJob& job = this->HeaderJobs[std::move(header)];
- job.Moc = moc;
- job.Uic = uic;
- }
- }
- }
- }
- // Add Source jobs
- for (std::string& src : sources) {
- AddJob(this->SourceJobs, std::move(src));
- }
- }
- }
-
- // Init derived information
- // ------------------------
-
- // Init file path checksum generator
- this->FilePathChecksum.setupParentDirs(
- this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir,
- this->ProjectBinaryDir);
-
- // include directory
- this->AutogenIncludeDir = "include";
- if (this->MultiConfig != cmQtAutoGen::SINGLE) {
- this->AutogenIncludeDir += this->ConfigSuffix;
- }
- this->AutogenIncludeDir += "/";
-
- // Moc variables
- if (this->MocEnabled()) {
- // Mocs compilation file
- this->MocCompFileRel = "mocs_compilation";
- if (this->MultiConfig == cmQtAutoGen::FULL) {
- this->MocCompFileRel += this->ConfigSuffix;
- }
- this->MocCompFileRel += ".cpp";
- this->MocCompFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->MocCompFileRel);
-
- // Moc predefs file
- if (!this->MocPredefsCmd.empty()) {
- this->MocPredefsFileRel = "moc_predefs";
- if (this->MultiConfig != cmQtAutoGen::SINGLE) {
- this->MocPredefsFileRel += this->ConfigSuffix;
- }
- this->MocPredefsFileRel += ".h";
- this->MocPredefsFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->MocPredefsFileRel);
- }
-
- // Sort include directories on demand
- if (this->IncludeProjectDirsBefore) {
- // Move strings to temporary list
- std::list<std::string> includes;
- includes.insert(includes.end(), this->MocIncludePaths.begin(),
- this->MocIncludePaths.end());
- this->MocIncludePaths.clear();
- this->MocIncludePaths.reserve(includes.size());
- // Append project directories only
- {
- std::array<std::string const*, 2> const movePaths = {
- { &this->ProjectBinaryDir, &this->ProjectSourceDir }
- };
- for (std::string const* ppath : movePaths) {
- std::list<std::string>::iterator it = includes.begin();
- while (it != includes.end()) {
- std::string const& path = *it;
- if (cmSystemTools::StringStartsWith(path, ppath->c_str())) {
- this->MocIncludePaths.push_back(path);
- it = includes.erase(it);
- } else {
- ++it;
- }
- }
- }
- }
- // Append remaining directories
- this->MocIncludePaths.insert(this->MocIncludePaths.end(),
- includes.begin(), includes.end());
- }
- // Compose moc includes list
- {
- std::set<std::string> frameworkPaths;
- for (std::string const& path : this->MocIncludePaths) {
- this->MocIncludes.push_back("-I" + path);
- // Extract framework path
- if (cmHasLiteralSuffix(path, ".framework/Headers")) {
- // Go up twice to get to the framework root
- std::vector<std::string> pathComponents;
- cmSystemTools::SplitPath(path, pathComponents);
- std::string frameworkPath = cmSystemTools::JoinPath(
- pathComponents.begin(), pathComponents.end() - 2);
- frameworkPaths.insert(frameworkPath);
- }
- }
- // Append framework includes
- for (std::string const& path : frameworkPaths) {
- this->MocIncludes.push_back("-F");
- this->MocIncludes.push_back(path);
- }
- }
- // Setup single list with all options
- {
- // Add includes
- this->MocAllOptions.insert(this->MocAllOptions.end(),
- this->MocIncludes.begin(),
- this->MocIncludes.end());
- // Add definitions
- for (std::string const& def : this->MocDefinitions) {
- this->MocAllOptions.push_back("-D" + def);
- }
- // Add options
- this->MocAllOptions.insert(this->MocAllOptions.end(),
- this->MocOptions.begin(),
- this->MocOptions.end());
- }
- }
-
- // - 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)
-{
- // Compose current settings strings
- {
- cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
- std::string const sep(" ~~~ ");
- if (this->MocEnabled()) {
- std::string str;
- str += this->MocExecutable;
- str += sep;
- str += cmJoin(this->MocAllOptions, ";");
- str += sep;
- str += this->IncludeProjectDirsBefore ? "TRUE" : "FALSE";
- str += sep;
- str += cmJoin(this->MocPredefsCmd, ";");
- str += sep;
- this->SettingsStringMoc = crypt.HashString(str);
- }
- if (this->UicEnabled()) {
- std::string str;
- str += this->UicExecutable;
- str += sep;
- str += cmJoin(this->UicTargetOptions, ";");
- for (const auto& item : this->UicOptions) {
- str += sep;
- str += item.first;
- str += sep;
- str += cmJoin(item.second, ";");
- }
- 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
- if (makefile->ReadListFile(this->SettingsFile.c_str())) {
- {
- auto SMatch = [makefile](const char* key, std::string const& value) {
- return (value == makefile->GetSafeDefinition(key));
- };
- if (!SMatch(SettingsKeyMoc, this->SettingsStringMoc)) {
- this->MocSettingsChanged = true;
- }
- 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
- // 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->MocSettingsChanged = true;
- this->UicSettingsChanged = true;
- this->RccSettingsChanged = true;
- }
-}
-
-bool cmQtAutoGenerators::SettingsFileWrite()
-{
- bool success = true;
- // Only write if any setting changed
- if (this->SettingsChanged()) {
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::GEN, "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(SettingsKeyMoc, this->SettingsStringMoc);
- SettingAppend(SettingsKeyUic, this->SettingsStringUic);
- SettingAppend(SettingsKeyRcc, this->SettingsStringRcc);
- }
- // Write settings file
- if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) {
- this->LogFileError(cmQtAutoGen::GEN, 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 cmQtAutoGenerators::Process()
-{
- // 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
- // what file the moc is created from. Once a moc is included the same moc
- // may not be included in the mocs_compilation.cpp file anymore.
- // OTOH if there's a header containing Q_OBJECT where no corresponding
- // moc file is included anywhere a moc_<filename>.cpp file is created and
- // included in the mocs_compilation.cpp file.
-
- // Create AUTOGEN include directory
- {
- std::string const incDirAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, this->AutogenIncludeDir);
- if (!cmSystemTools::MakeDirectory(incDirAbs)) {
- this->LogFileError(cmQtAutoGen::GEN, incDirAbs,
- "Could not create directory");
- return false;
- }
- }
-
- // Parse source files
- for (const auto& item : this->SourceJobs) {
- if (!this->ParseSourceFile(item.first, item.second)) {
- return false;
- }
- }
- // Parse header files
- for (const auto& item : this->HeaderJobs) {
- if (!this->ParseHeaderFile(item.first, item.second)) {
- return false;
- }
- }
- // Read missing dependency information
- if (!this->ParsePostprocess()) {
- return false;
- }
-
- // Generate files
- if (!this->MocGenerateAll()) {
- return false;
- }
- if (!this->UicGenerateAll()) {
- return false;
- }
- if (!this->RccGenerateAll()) {
- return false;
- }
-
- return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename,
- const SourceJob& job)
-{
- std::string contentText;
- std::string error;
- bool success = ReadFile(contentText, absFilename, &error);
- if (success) {
- if (!contentText.empty()) {
- if (job.Moc) {
- success = this->MocParseSourceContent(absFilename, contentText);
- }
- if (success && job.Uic) {
- success = this->UicParseContent(absFilename, contentText);
- }
- } else {
- this->LogFileWarning(cmQtAutoGen::GEN, absFilename,
- "The source file is empty");
- }
- } else {
- this->LogFileError(cmQtAutoGen::GEN, absFilename,
- "Could not read the source file: " + error);
- }
- return success;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename,
- const SourceJob& job)
-{
- std::string contentText;
- std::string error;
- bool success = ReadFile(contentText, absFilename, &error);
- if (success) {
- if (!contentText.empty()) {
- if (job.Moc) {
- this->MocParseHeaderContent(absFilename, contentText);
- }
- if (job.Uic) {
- success = this->UicParseContent(absFilename, contentText);
- }
- } else {
- this->LogFileWarning(cmQtAutoGen::GEN, absFilename,
- "The header file is empty");
- }
- } else {
- this->LogFileError(cmQtAutoGen::GEN, absFilename,
- "Could not read the header file: " + error);
- }
- return success;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::ParsePostprocess()
-{
- bool success = true;
- // Read missin dependecies
- for (auto& item : this->MocJobsIncluded) {
- if (!item->DependsValid) {
- std::string content;
- std::string error;
- if (ReadFile(content, item->SourceFile, &error)) {
- this->MocFindDepends(item->SourceFile, content, item->Depends);
- item->DependsValid = true;
- } else {
- std::string emsg = "Could not read file\n ";
- emsg += item->SourceFile;
- emsg += "\nrequired by moc include \"";
- emsg += item->IncludeString;
- emsg += "\".\n";
- emsg += error;
- this->LogFileError(cmQtAutoGen::MOC, item->Includer, emsg);
- success = false;
- break;
- }
- }
- }
- return success;
-}
-
-/**
- * @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
-{
- if (this->MocEnabled()) {
- // Test if the file name is on the skip list
- if (!ListContains(this->MocSkipList, absFilename)) {
- return false;
- }
- }
- return true;
-}
-
-/**
- * @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)
-{
- for (KeyRegExp& filter : this->MocMacroFilters) {
- // Run a simple find string operation before the expensive
- // regular expression check
- if (contentText.find(filter.Key) != std::string::npos) {
- if (filter.RegExp.find(contentText)) {
- // Return macro name on demand
- if (macroName != nullptr) {
- *macroName = filter.Key;
- }
- return true;
- }
- }
- }
- return false;
-}
-
-std::string cmQtAutoGenerators::MocStringMacros() const
-{
- std::string res;
- const auto itB = this->MocMacroFilters.cbegin();
- const auto itE = this->MocMacroFilters.cend();
- const auto itL = itE - 1;
- auto itC = itB;
- for (; itC != itE; ++itC) {
- // Separator
- if (itC != itB) {
- if (itC != itL) {
- res += ", ";
- } else {
- res += " or ";
- }
- }
- // Key
- res += itC->Key;
- }
- return res;
-}
-
-std::string cmQtAutoGenerators::MocStringHeaders(
- std::string const& fileBase) const
-{
- std::string res = fileBase;
- res += ".{";
- res += cmJoin(this->HeaderExtensions, ",");
- res += "}";
- return res;
-}
-
-std::string cmQtAutoGenerators::MocFindIncludedHeader(
- std::string const& sourcePath, std::string const& includeBase) const
-{
- std::string header;
- // Search in vicinity of the source
- if (!this->FindHeader(header, sourcePath + includeBase)) {
- // Search in include directories
- for (std::string const& path : this->MocIncludePaths) {
- std::string fullPath = path;
- fullPath.push_back('/');
- fullPath += includeBase;
- if (this->FindHeader(header, fullPath)) {
- break;
- }
- }
- }
- // Sanitize
- if (!header.empty()) {
- header = cmSystemTools::GetRealPath(header);
- }
- return header;
-}
-
-bool cmQtAutoGenerators::MocFindIncludedFile(
- std::string& absFile, std::string const& sourcePath,
- std::string const& includeString) const
-{
- bool success = false;
- // Search in vicinity of the source
- {
- std::string testPath = sourcePath;
- testPath += includeString;
- if (cmSystemTools::FileExists(testPath.c_str())) {
- absFile = cmSystemTools::GetRealPath(testPath);
- success = true;
- }
- }
- // Search in include directories
- if (!success) {
- for (std::string const& path : this->MocIncludePaths) {
- std::string fullPath = path;
- fullPath.push_back('/');
- fullPath += includeString;
- if (cmSystemTools::FileExists(fullPath.c_str())) {
- absFile = cmSystemTools::GetRealPath(fullPath);
- success = true;
- break;
- }
- }
- }
- return success;
-}
-
-bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key,
- std::string const& regExp)
-{
- std::string error;
- if (!key.empty()) {
- if (!regExp.empty()) {
- KeyRegExp filter;
- filter.Key = key;
- if (filter.RegExp.compile(regExp)) {
- this->MocDependFilters.push_back(std::move(filter));
- } else {
- error = "Regular expression compiling failed";
- }
- } else {
- error = "Regular expression is empty";
- }
- } else {
- error = "Key is empty";
- }
- if (!error.empty()) {
- std::string emsg = "AUTOMOC_DEPEND_FILTERS: ";
- emsg += error;
- emsg += "\n";
- emsg += " Key: ";
- emsg += cmQtAutoGen::Quoted(key);
- emsg += "\n";
- emsg += " RegExp: ";
- emsg += cmQtAutoGen::Quoted(regExp);
- emsg += "\n";
- this->LogError(cmQtAutoGen::MOC, emsg);
- return false;
- }
- return true;
-}
-
-void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename,
- std::string const& contentText,
- std::set<std::string>& depends)
-{
- if (this->MocDependFilters.empty() && contentText.empty()) {
- return;
- }
-
- std::vector<std::string> matches;
- for (KeyRegExp& filter : this->MocDependFilters) {
- // Run a simple find string check
- if (contentText.find(filter.Key) != std::string::npos) {
- // Run the expensive regular expression check loop
- const char* contentChars = contentText.c_str();
- while (filter.RegExp.find(contentChars)) {
- std::string match = filter.RegExp.match(1);
- if (!match.empty()) {
- matches.emplace_back(std::move(match));
- }
- contentChars += filter.RegExp.end();
- }
- }
- }
-
- if (!matches.empty()) {
- std::string const sourcePath = SubDirPrefix(absFilename);
- for (std::string const& match : matches) {
- // Find the dependency file
- std::string incFile;
- if (this->MocFindIncludedFile(incFile, sourcePath, match)) {
- depends.insert(incFile);
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " +
- cmQtAutoGen::Quoted(absFilename) + "\n " +
- cmQtAutoGen::Quoted(incFile));
- }
- } else {
- this->LogFileWarning(cmQtAutoGen::MOC, absFilename,
- "Could not find dependency file " +
- cmQtAutoGen::Quoted(match));
- }
- }
- }
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename,
- std::string const& contentText)
-{
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
- }
-
- auto AddJob = [this, &absFilename](std::string const& sourceFile,
- std::string const& includeString,
- std::string const* content) {
- auto job = cm::make_unique<MocJobIncluded>();
- job->SourceFile = sourceFile;
- job->BuildFileRel = this->AutogenIncludeDir;
- job->BuildFileRel += includeString;
- job->Includer = absFilename;
- job->IncludeString = includeString;
- job->DependsValid = (content != nullptr);
- if (job->DependsValid) {
- this->MocFindDepends(sourceFile, *content, job->Depends);
- }
- this->MocJobsIncluded.push_back(std::move(job));
- };
-
- struct MocInc
- {
- std::string Inc; // full include string
- std::string Dir; // include string directory
- std::string Base; // include string file base
- };
-
- // Extract moc includes from file
- std::vector<MocInc> mocIncsUsc;
- std::vector<MocInc> mocIncsDot;
- {
- const char* contentChars = contentText.c_str();
- if (strstr(contentChars, "moc") != nullptr) {
- while (this->MocRegExpInclude.find(contentChars)) {
- std::string incString = this->MocRegExpInclude.match(1);
- std::string incDir(SubDirPrefix(incString));
- std::string incBase =
- cmSystemTools::GetFilenameWithoutLastExtension(incString);
- if (cmHasLiteralPrefix(incBase, "moc_")) {
- // moc_<BASE>.cxx
- // Remove the moc_ part from the base name
- mocIncsUsc.push_back(MocInc{ std::move(incString), std::move(incDir),
- incBase.substr(4) });
- } else {
- // <BASE>.moc
- mocIncsDot.push_back(MocInc{ std::move(incString), std::move(incDir),
- std::move(incBase) });
- }
- // Forward content pointer
- contentChars += this->MocRegExpInclude.end();
- }
- }
- }
-
- std::string selfMacroName;
- const bool selfRequiresMoc = this->MocRequired(contentText, &selfMacroName);
-
- // Check if there is anything to do
- if (!selfRequiresMoc && mocIncsUsc.empty() && mocIncsDot.empty()) {
- return true;
- }
-
- // Scan file variables
- std::string const scanFileDir = SubDirPrefix(absFilename);
- std::string const scanFileBase =
- cmSystemTools::GetFilenameWithoutLastExtension(absFilename);
- // Relaxed mode variables
- bool ownDotMocIncluded = false;
- std::string ownMocUscInclude;
- std::string ownMocUscHeader;
-
- // Process moc_<BASE>.cxx includes
- for (const MocInc& mocInc : mocIncsUsc) {
- std::string const header =
- this->MocFindIncludedHeader(scanFileDir, mocInc.Dir + mocInc.Base);
- if (!header.empty()) {
- // Check if header is skipped
- if (this->MocSkip(header)) {
- continue;
- }
- // Register moc job
- AddJob(header, mocInc.Inc, nullptr);
- // Store meta information for relaxed mode
- if (this->MocRelaxedMode && (mocInc.Base == scanFileBase)) {
- ownMocUscInclude = mocInc.Inc;
- ownMocUscHeader = header;
- }
- } else {
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += ", but could not find the header ";
- emsg += cmQtAutoGen::Quoted(this->MocStringHeaders(mocInc.Base));
- this->LogFileError(cmQtAutoGen::MOC, absFilename, emsg);
- return false;
- }
- }
-
- // Process <BASE>.moc includes
- for (const MocInc& mocInc : mocIncsDot) {
- const bool ownMoc = (mocInc.Base == scanFileBase);
- if (this->MocRelaxedMode) {
- // Relaxed mode
- if (selfRequiresMoc && ownMoc) {
- // Add self
- AddJob(absFilename, mocInc.Inc, &contentText);
- ownDotMocIncluded = true;
- } else {
- // In relaxed mode try to find a header instead but issue a warning.
- // This is for KDE4 compatibility
- std::string const header =
- this->MocFindIncludedHeader(scanFileDir, mocInc.Dir + mocInc.Base);
- if (!header.empty()) {
- // Check if header is skipped
- if (this->MocSkip(header)) {
- continue;
- }
- // Register moc job
- AddJob(header, mocInc.Inc, nullptr);
- if (!selfRequiresMoc) {
- if (ownMoc) {
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += ", but does not contain a ";
- emsg += this->MocStringMacros();
- emsg += " macro.\nRunning moc on\n ";
- emsg += cmQtAutoGen::Quoted(header);
- emsg += "!\nBetter include ";
- emsg += cmQtAutoGen::Quoted("moc_" + mocInc.Base + ".cpp");
- emsg += " for a compatibility with strict mode.\n"
- "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
- this->LogFileWarning(cmQtAutoGen::MOC, absFilename, emsg);
- } else {
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += " instead of ";
- emsg += cmQtAutoGen::Quoted("moc_" + mocInc.Base + ".cpp");
- emsg += ".\nRunning moc on\n ";
- emsg += cmQtAutoGen::Quoted(header);
- emsg += "!\nBetter include ";
- emsg += cmQtAutoGen::Quoted("moc_" + mocInc.Base + ".cpp");
- emsg += " for compatibility with strict mode.\n"
- "(CMAKE_AUTOMOC_RELAXED_MODE warning)\n";
- this->LogFileWarning(cmQtAutoGen::MOC, absFilename, emsg);
- }
- }
- } else {
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += ", which seems to be the moc file from a different "
- "source file. CMake also could not find a matching "
- "header.";
- this->LogFileError(cmQtAutoGen::MOC, absFilename, emsg);
- return false;
- }
- }
- } else {
- // Strict mode
- if (ownMoc) {
- // Include self
- AddJob(absFilename, mocInc.Inc, &contentText);
- ownDotMocIncluded = true;
- // Accept but issue a warning if moc isn't required
- if (!selfRequiresMoc) {
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += ", but does not contain a ";
- emsg += this->MocStringMacros();
- emsg += " macro.";
- this->LogFileWarning(cmQtAutoGen::MOC, absFilename, emsg);
- }
- } else {
- // Don't allow <BASE>.moc include other than self in strict mode
- std::string emsg = "The file includes the moc file ";
- emsg += cmQtAutoGen::Quoted(mocInc.Inc);
- emsg += ", which seems to be the moc file from a different "
- "source file.\nThis is not supported. Include ";
- emsg += cmQtAutoGen::Quoted(scanFileBase + ".moc");
- emsg += " to run moc on this source file.";
- this->LogFileError(cmQtAutoGen::MOC, absFilename, emsg);
- return false;
- }
- }
- }
-
- if (selfRequiresMoc && !ownDotMocIncluded) {
- // In this case, check whether the scanned file itself contains a Q_OBJECT.
- // If this is the case, the moc_foo.cpp should probably be generated from
- // foo.cpp instead of foo.h, because otherwise it won't build.
- // But warn, since this is not how it is supposed to be used.
- if (this->MocRelaxedMode && !ownMocUscInclude.empty()) {
- // This is for KDE4 compatibility:
- std::string emsg = "The file contains a ";
- emsg += selfMacroName;
- emsg += " macro, but does not include ";
- emsg += cmQtAutoGen::Quoted(scanFileBase + ".moc");
- emsg += ". Instead it includes ";
- emsg += cmQtAutoGen::Quoted(ownMocUscInclude);
- emsg += ".\nRunning moc on\n ";
- emsg += cmQtAutoGen::Quoted(absFilename);
- emsg += "!\nBetter include ";
- emsg += cmQtAutoGen::Quoted(scanFileBase + ".moc");
- emsg += " for compatibility with strict mode.\n"
- "(CMAKE_AUTOMOC_RELAXED_MODE warning)";
- this->LogFileWarning(cmQtAutoGen::MOC, absFilename, emsg);
-
- // Remove own header job
- {
- auto itC = this->MocJobsIncluded.begin();
- auto itE = this->MocJobsIncluded.end();
- for (; itC != itE; ++itC) {
- if ((*itC)->SourceFile == ownMocUscHeader) {
- if ((*itC)->IncludeString == ownMocUscInclude) {
- this->MocJobsIncluded.erase(itC);
- break;
- }
- }
- }
- }
- // Add own source job
- AddJob(absFilename, ownMocUscInclude, &contentText);
- } else {
- // Otherwise always error out since it will not compile:
- std::string emsg = "The file contains a ";
- emsg += selfMacroName;
- emsg += " macro, but does not include ";
- emsg += cmQtAutoGen::Quoted(scanFileBase + ".moc");
- emsg += "!\nConsider to\n - add #include \"";
- emsg += scanFileBase;
- emsg += ".moc\"\n - enable SKIP_AUTOMOC for this file";
- this->LogFileError(cmQtAutoGen::MOC, absFilename, emsg);
- return false;
- }
- }
- return true;
-}
-
-void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename,
- std::string const& contentText)
-{
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename);
- }
-
- auto const fit =
- std::find_if(this->MocJobsIncluded.cbegin(), this->MocJobsIncluded.cend(),
- [&absFilename](std::unique_ptr<MocJobIncluded> const& job) {
- return job->SourceFile == absFilename;
- });
- if (fit == this->MocJobsIncluded.cend()) {
- if (this->MocRequired(contentText)) {
- auto job = cm::make_unique<MocJobAuto>();
- job->SourceFile = absFilename;
- {
- std::string& bld = job->BuildFileRel;
- bld = this->FilePathChecksum.getPart(absFilename);
- bld += '/';
- bld += "moc_";
- bld += cmSystemTools::GetFilenameWithoutLastExtension(absFilename);
- if (this->MultiConfig != cmQtAutoGen::SINGLE) {
- bld += this->ConfigSuffix;
- }
- bld += ".cpp";
- }
- this->MocFindDepends(absFilename, contentText, job->Depends);
- this->MocJobsAuto.push_back(std::move(job));
- }
- }
-}
-
-bool cmQtAutoGenerators::MocGenerateAll()
-{
- if (!this->MocEnabled()) {
- return true;
- }
-
- // Look for name collisions in included moc files
- {
- bool collision = false;
- std::map<std::string, std::vector<MocJobIncluded const*>> collisions;
- for (auto const& job : this->MocJobsIncluded) {
- auto& list = collisions[job->IncludeString];
- if (!list.empty()) {
- collision = true;
- }
- list.push_back(job.get());
- }
- if (collision) {
- std::string emsg =
- "Included moc files with the same name will be "
- "generated from different sources.\n"
- "Consider to\n"
- " - not include the \"moc_<NAME>.cpp\" file\n"
- " - add a directory prefix to a \"<NAME>.moc\" include "
- "(e.g \"sub/<NAME>.moc\")\n"
- " - rename the source file(s)\n"
- "Include conflicts\n"
- "-----------------\n";
- const auto& colls = collisions;
- for (auto const& coll : colls) {
- if (coll.second.size() > 1) {
- emsg += cmQtAutoGen::Quoted(coll.first);
- emsg += " included in\n";
- for (const MocJobIncluded* job : coll.second) {
- emsg += " - ";
- emsg += cmQtAutoGen::Quoted(job->Includer);
- emsg += "\n";
- }
- emsg += "would be generated from\n";
- for (const MocJobIncluded* job : coll.second) {
- emsg += " - ";
- emsg += cmQtAutoGen::Quoted(job->SourceFile);
- emsg += "\n";
- }
- }
- }
- this->LogError(cmQtAutoGen::MOC, emsg);
- return false;
- }
- }
-
- // (Re)generate moc_predefs.h on demand
- if (!this->MocPredefsCmd.empty()) {
- if (this->MocSettingsChanged ||
- !cmSystemTools::FileExists(this->MocPredefsFileAbs)) {
- if (this->Verbose) {
- this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel);
- }
-
- std::string output;
- {
- // Compose command
- std::vector<std::string> cmd = this->MocPredefsCmd;
- // Add includes
- cmd.insert(cmd.end(), this->MocIncludes.begin(),
- this->MocIncludes.end());
- // Add definitions
- for (std::string const& def : this->MocDefinitions) {
- cmd.push_back("-D" + def);
- }
- // Execute command
- if (!this->RunCommand(cmd, output)) {
- this->LogCommandError(cmQtAutoGen::MOC,
- "moc_predefs generation failed", cmd, output);
- return false;
- }
- }
-
- // (Re)write predefs file only on demand
- if (this->FileDiffers(this->MocPredefsFileAbs, output)) {
- if (this->FileWrite(cmQtAutoGen::MOC, this->MocPredefsFileAbs,
- output)) {
- this->MocPredefsChanged = true;
- } else {
- this->LogFileError(cmQtAutoGen::MOC, this->MocPredefsFileAbs,
- "moc_predefs file writing failed");
- return false;
- }
- } else {
- // Touch to update the time stamp
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::MOC,
- "Touching moc_predefs " + this->MocPredefsFileRel);
- }
- cmSystemTools::Touch(this->MocPredefsFileAbs, false);
- }
- }
-
- // Add moc_predefs.h to moc file dependecies
- for (auto const& item : this->MocJobsIncluded) {
- item->Depends.insert(this->MocPredefsFileAbs);
- }
- for (auto const& item : this->MocJobsAuto) {
- item->Depends.insert(this->MocPredefsFileAbs);
- }
- }
-
- // Generate moc files that are included by source files.
- for (auto const& item : this->MocJobsIncluded) {
- if (!this->MocGenerateFile(*item)) {
- return false;
- }
- }
- // Generate moc files that are _not_ included by source files.
- bool autoNameGenerated = false;
- for (auto const& item : this->MocJobsAuto) {
- if (!this->MocGenerateFile(*item, &autoNameGenerated)) {
- return false;
- }
- }
-
- // Compose mocs compilation file content
- {
- std::string mocs =
- "// This file is autogenerated. Changes will be overwritten.\n";
- if (this->MocJobsAuto.empty()) {
- // Placeholder content
- mocs +=
- "// No files found that require moc or the moc files are included\n";
- mocs += "enum some_compilers { need_more_than_nothing };\n";
- } else {
- // Valid content
- for (const auto& item : this->MocJobsAuto) {
- mocs += "#include \"";
- mocs += item->BuildFileRel;
- mocs += "\"\n";
- }
- }
-
- if (this->FileDiffers(this->MocCompFileAbs, mocs)) {
- // Actually write mocs compilation file
- if (this->Verbose) {
- this->LogBold("Generating MOC compilation " + this->MocCompFileRel);
- }
- if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) {
- this->LogFileError(cmQtAutoGen::MOC, this->MocCompFileAbs,
- "mocs compilation file writing failed");
- return false;
- }
- } else if (autoNameGenerated) {
- // Only touch mocs compilation file
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::MOC,
- "Touching mocs compilation " + this->MocCompFileRel);
- }
- cmSystemTools::Touch(this->MocCompFileAbs, false);
- }
- }
-
- return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob,
- bool* generated)
-{
- bool success = true;
-
- std::string const mocFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, mocJob.BuildFileRel);
-
- bool generate = false;
- std::string generateReason;
- if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(mocFileAbs);
- generateReason += " from its source file ";
- generateReason += cmQtAutoGen::Quoted(mocJob.SourceFile);
- generateReason += " because it doesn't exist";
- }
- generate = true;
- }
- if (!generate && this->MocSettingsChanged) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(mocFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(mocJob.SourceFile);
- generateReason += " because the MOC settings changed";
- }
- generate = true;
- }
- if (!generate && this->MocPredefsChanged) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(mocFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(mocJob.SourceFile);
- generateReason += " because moc_predefs.h changed";
- }
- generate = true;
- }
- if (!generate) {
- std::string error;
- if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(mocFileAbs);
- generateReason += " because it's older than its source file ";
- generateReason += cmQtAutoGen::Quoted(mocJob.SourceFile);
- }
- generate = true;
- } else {
- if (!error.empty()) {
- this->LogError(cmQtAutoGen::MOC, error);
- success = false;
- }
- }
- }
- if (success && !generate) {
- // Test if a dependency file is newer
- std::string error;
- for (std::string const& depFile : mocJob.Depends) {
- if (FileIsOlderThan(mocFileAbs, depFile, &error)) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(mocFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(mocJob.SourceFile);
- generateReason += " because it is older than ";
- generateReason += cmQtAutoGen::Quoted(depFile);
- }
- generate = true;
- break;
- }
- if (!error.empty()) {
- this->LogError(cmQtAutoGen::MOC, error);
- success = false;
- break;
- }
- }
- }
-
- if (generate) {
- // Log
- if (this->Verbose) {
- this->LogBold("Generating MOC source " + mocJob.BuildFileRel);
- this->LogInfo(cmQtAutoGen::MOC, generateReason);
- }
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory(cmQtAutoGen::MOC, mocFileAbs)) {
- // Compose moc command
- std::vector<std::string> cmd;
- cmd.push_back(this->MocExecutable);
- // Add options
- cmd.insert(cmd.end(), this->MocAllOptions.begin(),
- this->MocAllOptions.end());
- // Add predefs include
- if (!this->MocPredefsFileAbs.empty()) {
- cmd.push_back("--include");
- cmd.push_back(this->MocPredefsFileAbs);
- }
- cmd.push_back("-o");
- cmd.push_back(mocFileAbs);
- cmd.push_back(mocJob.SourceFile);
-
- // Execute moc command
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- if (generated != nullptr) {
- *generated = true;
- }
- } else {
- // Moc command failed
- {
- std::string emsg = "moc failed for\n ";
- emsg += cmQtAutoGen::Quoted(mocJob.SourceFile);
- this->LogCommandError(cmQtAutoGen::MOC, emsg, cmd, output);
- }
- cmSystemTools::RemoveFile(mocFileAbs);
- success = false;
- }
- } else {
- // Parent directory creation failed
- success = false;
- }
- }
- return success;
-}
-
-/**
- * @brief Tests if the file name is in the skip list
- */
-bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const
-{
- if (this->UicEnabled()) {
- // Test if the file name is on the skip list
- if (!ListContains(this->UicSkipList, absFilename)) {
- return false;
- }
- }
- return true;
-}
-
-bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename,
- std::string const& contentText)
-{
- if (this->Verbose) {
- this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename);
- }
-
- std::vector<std::string> includes;
- // Extracte includes
- {
- const char* contentChars = contentText.c_str();
- if (strstr(contentChars, "ui_") != nullptr) {
- while (this->UicRegExpInclude.find(contentChars)) {
- includes.push_back(this->UicRegExpInclude.match(1));
- contentChars += this->UicRegExpInclude.end();
- }
- }
- }
-
- for (std::string const& includeString : includes) {
- std::string uiInputFile;
- if (!UicFindIncludedFile(uiInputFile, absFilename, includeString)) {
- return false;
- }
- // Check if this file should be skipped
- if (this->UicSkip(uiInputFile)) {
- continue;
- }
- // Check if the job already exists
- bool jobExists = false;
- for (const auto& job : this->UicJobs) {
- if ((job->SourceFile == uiInputFile) &&
- (job->IncludeString == includeString)) {
- jobExists = true;
- break;
- }
- }
- if (!jobExists) {
- auto job = cm::make_unique<UicJob>();
- job->SourceFile = uiInputFile;
- job->BuildFileRel = this->AutogenIncludeDir;
- job->BuildFileRel += includeString;
- job->Includer = absFilename;
- job->IncludeString = includeString;
- this->UicJobs.push_back(std::move(job));
- }
- }
-
- return true;
-}
-
-bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile,
- std::string const& sourceFile,
- std::string const& includeString)
-{
- bool success = false;
- std::string searchFile =
- cmSystemTools::GetFilenameWithoutLastExtension(includeString).substr(3);
- searchFile += ".ui";
- // Collect search paths list
- std::vector<std::string> testFiles;
- {
- std::string const searchPath = SubDirPrefix(includeString);
-
- std::string searchFileFull;
- if (!searchPath.empty()) {
- searchFileFull = searchPath;
- searchFileFull += searchFile;
- }
- // Vicinity of the source
- {
- std::string const sourcePath = SubDirPrefix(sourceFile);
- testFiles.push_back(sourcePath + searchFile);
- if (!searchPath.empty()) {
- testFiles.push_back(sourcePath + searchFileFull);
- }
- }
- // AUTOUIC search paths
- if (!this->UicSearchPaths.empty()) {
- for (std::string const& sPath : this->UicSearchPaths) {
- testFiles.push_back((sPath + "/").append(searchFile));
- }
- if (!searchPath.empty()) {
- for (std::string const& sPath : this->UicSearchPaths) {
- testFiles.push_back((sPath + "/").append(searchFileFull));
- }
- }
- }
- }
-
- // Search for the .ui file!
- for (std::string const& testFile : testFiles) {
- if (cmSystemTools::FileExists(testFile.c_str())) {
- absFile = cmSystemTools::GetRealPath(testFile);
- success = true;
- break;
- }
- }
-
- // Log error
- if (!success) {
- std::string emsg = "Could not find ";
- emsg += cmQtAutoGen::Quoted(searchFile);
- emsg += " in\n";
- for (std::string const& testFile : testFiles) {
- emsg += " ";
- emsg += cmQtAutoGen::Quoted(testFile);
- emsg += "\n";
- }
- this->LogFileError(cmQtAutoGen::UIC, sourceFile, emsg);
- }
-
- return success;
-}
-
-bool cmQtAutoGenerators::UicGenerateAll()
-{
- if (!this->UicEnabled()) {
- return true;
- }
-
- // Look for name collisions in included uic files
- {
- bool collision = false;
- std::map<std::string, std::vector<UicJob const*>> collisions;
- for (auto const& job : this->UicJobs) {
- auto& list = collisions[job->IncludeString];
- if (!list.empty()) {
- collision = true;
- }
- list.push_back(job.get());
- }
- if (collision) {
- std::string emsg =
- "Included uic files with the same name will be "
- "generated from different sources.\n"
- "Consider to\n"
- " - add a directory prefix to a \"ui_<NAME>.h\" include "
- "(e.g \"sub/ui_<NAME>.h\")\n"
- " - rename the <NAME>.ui file(s) and adjust the \"ui_<NAME>.h\" "
- "include(s)\n"
- "Include conflicts\n"
- "-----------------\n";
- const auto& colls = collisions;
- for (auto const& coll : colls) {
- if (coll.second.size() > 1) {
- emsg += cmQtAutoGen::Quoted(coll.first);
- emsg += " included in\n";
- for (const UicJob* job : coll.second) {
- emsg += " - ";
- emsg += cmQtAutoGen::Quoted(job->Includer);
- emsg += "\n";
- }
- emsg += "would be generated from\n";
- for (const UicJob* job : coll.second) {
- emsg += " - ";
- emsg += cmQtAutoGen::Quoted(job->SourceFile);
- emsg += "\n";
- }
- }
- }
- this->LogError(cmQtAutoGen::UIC, emsg);
- return false;
- }
- }
-
- // Generate ui header files
- for (const auto& item : this->UicJobs) {
- if (!this->UicGenerateFile(*item)) {
- return false;
- }
- }
-
- return true;
-}
-
-/**
- * @return True on success
- */
-bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob)
-{
- bool success = true;
-
- std::string const uicFileAbs = cmSystemTools::CollapseCombinedPath(
- this->AutogenBuildDir, uicJob.BuildFileRel);
-
- bool generate = false;
- std::string generateReason;
- if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(uicFileAbs);
- generateReason += " from its source file ";
- generateReason += cmQtAutoGen::Quoted(uicJob.SourceFile);
- generateReason += " because it doesn't exist";
- }
- generate = true;
- }
- if (!generate && this->UicSettingsChanged) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(uicFileAbs);
- generateReason += " from ";
- generateReason += cmQtAutoGen::Quoted(uicJob.SourceFile);
- generateReason += " because the UIC settings changed";
- }
- generate = true;
- }
- if (!generate) {
- std::string error;
- if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) {
- if (this->Verbose) {
- generateReason = "Generating ";
- generateReason += cmQtAutoGen::Quoted(uicFileAbs);
- generateReason += " because it's older than its source file ";
- generateReason += cmQtAutoGen::Quoted(uicJob.SourceFile);
- }
- generate = true;
- } else {
- if (!error.empty()) {
- this->LogError(cmQtAutoGen::UIC, error);
- success = false;
- }
- }
- }
- if (generate) {
- // Log
- if (this->Verbose) {
- this->LogBold("Generating UIC header " + uicJob.BuildFileRel);
- this->LogInfo(cmQtAutoGen::UIC, generateReason);
- }
-
- // Make sure the parent directory exists
- if (this->MakeParentDirectory(cmQtAutoGen::UIC, uicFileAbs)) {
- // Compose uic command
- std::vector<std::string> cmd;
- cmd.push_back(this->UicExecutable);
- {
- std::vector<std::string> allOpts = this->UicTargetOptions;
- auto optionIt = this->UicOptions.find(uicJob.SourceFile);
- if (optionIt != this->UicOptions.end()) {
- cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second,
- (this->QtMajorVersion == "5"));
- }
- cmd.insert(cmd.end(), allOpts.begin(), allOpts.end());
- }
- cmd.push_back("-o");
- cmd.push_back(uicFileAbs);
- cmd.push_back(uicJob.SourceFile);
-
- std::string output;
- if (this->RunCommand(cmd, output)) {
- // Success
- } else {
- // Command failed
- {
- std::string emsg = "uic failed for\n ";
- emsg += cmQtAutoGen::Quoted(uicJob.SourceFile);
- emsg += "\nincluded by\n ";
- emsg += cmQtAutoGen::Quoted(uicJob.Includer);
- this->LogCommandError(cmQtAutoGen::UIC, emsg, cmd, output);
- }
- cmSystemTools::RemoveFile(uicFileAbs);
- success = false;
- }
- } else {
- // Parent directory creation failed
- success = false;
- }
- }
- 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
-{
- for (std::string const& ext : this->HeaderExtensions) {
- std::string testFilePath(testBasePath);
- testFilePath.push_back('.');
- testFilePath += ext;
- if (cmSystemTools::FileExists(testFilePath.c_str())) {
- header = testFilePath;
- return true;
- }
- }
- return false;
-}
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
deleted file mode 100644
index a7bb53840..000000000
--- a/Source/cmQtAutoGenerators.h
+++ /dev/null
@@ -1,248 +0,0 @@
-/* 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
-
-#include "cmConfigure.h" // IWYU pragma: keep
-
-#include "cmFilePathChecksum.h"
-#include "cmQtAutoGen.h"
-#include "cmsys/RegularExpression.hxx"
-
-#include <map>
-#include <memory> // IWYU pragma: keep
-#include <set>
-#include <string>
-#include <vector>
-
-class cmMakefile;
-
-class cmQtAutoGenerators
-{
- CM_DISABLE_COPY(cmQtAutoGenerators)
-public:
- cmQtAutoGenerators();
- bool Run(std::string const& targetDirectory, std::string const& config);
-
-private:
- // -- Types
-
- /// @brief Search key plus regular expression pair
- struct KeyRegExp
- {
- KeyRegExp() = default;
-
- KeyRegExp(const char* key, const char* regExp)
- : Key(key)
- , RegExp(regExp)
- {
- }
-
- KeyRegExp(std::string const& key, std::string const& regExp)
- : Key(key)
- , RegExp(regExp)
- {
- }
-
- std::string Key;
- cmsys::RegularExpression RegExp;
- };
-
- /// @brief Source file job
- struct SourceJob
- {
- bool Moc = false;
- bool Uic = false;
- };
-
- /// @brief MOC job
- struct MocJobAuto
- {
- std::string SourceFile;
- std::string BuildFileRel;
- std::set<std::string> Depends;
- };
-
- /// @brief MOC job
- struct MocJobIncluded : MocJobAuto
- {
- bool DependsValid = false;
- std::string Includer;
- std::string IncludeString;
- };
-
- /// @brief UIC job
- struct UicJob
- {
- std::string SourceFile;
- std::string BuildFileRel;
- std::string Includer;
- 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);
-
- // -- Settings file
- void SettingsFileRead(cmMakefile* makefile);
- bool SettingsFileWrite();
- bool SettingsChanged() const
- {
- return (this->MocSettingsChanged || this->RccSettingsChanged ||
- this->UicSettingsChanged);
- }
-
- // -- Central processing
- bool Process();
-
- // -- Source parsing
- bool ParseSourceFile(std::string const& absFilename, const SourceJob& job);
- bool ParseHeaderFile(std::string const& absFilename, const SourceJob& job);
- bool ParsePostprocess();
-
- // -- Moc
- bool MocEnabled() const { return !this->MocExecutable.empty(); }
- bool MocSkip(std::string const& absFilename) const;
- bool MocRequired(std::string const& contentText,
- std::string* macroName = nullptr);
- // Moc strings
- std::string MocStringMacros() const;
- std::string MocStringHeaders(std::string const& fileBase) const;
- std::string MocFindIncludedHeader(std::string const& sourcePath,
- std::string const& includeBase) const;
- bool MocFindIncludedFile(std::string& absFile, std::string const& sourceFile,
- std::string const& includeString) const;
- // Moc depends
- bool MocDependFilterPush(std::string const& key, std::string const& regExp);
- void MocFindDepends(std::string const& absFilename,
- std::string const& contentText,
- std::set<std::string>& depends);
- // Moc
- bool MocParseSourceContent(std::string const& absFilename,
- std::string const& contentText);
- void MocParseHeaderContent(std::string const& absFilename,
- std::string const& contentText);
-
- bool MocGenerateAll();
- bool MocGenerateFile(const MocJobAuto& mocJob, bool* generated = nullptr);
-
- // -- Uic
- bool UicEnabled() const { return !this->UicExecutable.empty(); }
- bool UicSkip(std::string const& absFilename) const;
- bool UicParseContent(std::string const& fileName,
- std::string const& contentText);
- bool UicFindIncludedFile(std::string& absFile, std::string const& sourceFile,
- std::string const& includeString);
- 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;
- std::string CurrentSourceDir;
- std::string CurrentBinaryDir;
- std::string AutogenBuildDir;
- std::string AutogenIncludeDir;
- // -- Qt environment
- std::string QtMajorVersion;
- std::string QtMinorVersion;
- std::string MocExecutable;
- std::string UicExecutable;
- std::string RccExecutable;
- // -- File lists
- std::map<std::string, SourceJob> HeaderJobs;
- std::map<std::string, SourceJob> SourceJobs;
- std::vector<std::string> HeaderExtensions;
- cmFilePathChecksum FilePathChecksum;
- // -- Moc
- bool MocSettingsChanged;
- bool MocPredefsChanged;
- bool MocRelaxedMode;
- std::string MocCompFileRel;
- std::string MocCompFileAbs;
- std::string MocPredefsFileRel;
- std::string MocPredefsFileAbs;
- std::vector<std::string> MocSkipList;
- std::vector<std::string> MocIncludePaths;
- std::vector<std::string> MocIncludes;
- std::vector<std::string> MocDefinitions;
- std::vector<std::string> MocOptions;
- std::vector<std::string> MocAllOptions;
- std::vector<std::string> MocPredefsCmd;
- std::vector<KeyRegExp> MocDependFilters;
- std::vector<KeyRegExp> MocMacroFilters;
- cmsys::RegularExpression MocRegExpInclude;
- std::vector<std::unique_ptr<MocJobIncluded>> MocJobsIncluded;
- std::vector<std::unique_ptr<MocJobAuto>> MocJobsAuto;
- // -- Uic
- bool UicSettingsChanged;
- std::vector<std::string> UicSkipList;
- std::vector<std::string> UicTargetOptions;
- std::map<std::string, std::vector<std::string>> UicOptions;
- 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/cmRemoveDefinitionsCommand.cxx b/Source/cmRemoveDefinitionsCommand.cxx
index 8311b4b2f..8d3f6889e 100644
--- a/Source/cmRemoveDefinitionsCommand.cxx
+++ b/Source/cmRemoveDefinitionsCommand.cxx
@@ -16,7 +16,7 @@ bool cmRemoveDefinitionsCommand::InitialPass(
}
for (std::string const& i : args) {
- this->Makefile->RemoveDefineFlag(i.c_str());
+ this->Makefile->RemoveDefineFlag(i);
}
return true;
}
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index a40c98706..5b2986880 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -155,7 +155,7 @@ void cmSearchPath::AddSuffixes(const std::vector<std::string>& suffixes)
}
// And now the original w/o any suffix
- this->Paths.push_back(inPath);
+ this->Paths.push_back(std::move(inPath));
}
}
@@ -212,6 +212,6 @@ void cmSearchPath::AddPathInternal(const std::string& path, const char* base)
// Insert the path if has not already been emitted.
if (this->FC->SearchPathsEmitted.insert(collapsed).second) {
- this->Paths.push_back(collapsed);
+ this->Paths.push_back(std::move(collapsed));
}
}
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
index e923c228a..1b04ca287 100644
--- a/Source/cmServer.cxx
+++ b/Source/cmServer.cxx
@@ -18,17 +18,19 @@
#include <cstdint>
#include <iostream>
#include <memory>
+#include <mutex>
#include <utility>
void on_signal(uv_signal_t* signal, int signum)
{
- auto conn = reinterpret_cast<cmServerBase*>(signal->data);
+ auto conn = static_cast<cmServerBase*>(signal->data);
conn->OnSignal(signum);
}
static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
{
(void)arg;
+ assert(uv_is_closing(handle));
if (!uv_is_closing(handle)) {
uv_close(handle, &cmEventBasedConnection::on_close);
}
@@ -58,6 +60,8 @@ cmServer::cmServer(cmConnection* conn, bool supportExperimental)
cmServer::~cmServer()
{
+ Close();
+
for (cmServerProtocol* p : this->SupportedProtocols) {
delete p;
}
@@ -245,11 +249,10 @@ cmFileMonitor* cmServer::FileMonitor() const
void cmServer::WriteJsonObject(const Json::Value& jsonValue,
const DebugInfo* debug) const
{
- uv_rwlock_rdlock(&ConnectionsMutex);
+ cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
for (auto& connection : this->Connections) {
WriteJsonObject(connection.get(), jsonValue, debug);
}
- uv_rwlock_rdunlock(&ConnectionsMutex);
}
void cmServer::WriteJsonObject(cmConnection* connection,
@@ -410,7 +413,7 @@ void cmServer::StartShutDown()
static void __start_thread(void* arg)
{
- auto server = reinterpret_cast<cmServerBase*>(arg);
+ auto server = static_cast<cmServerBase*>(arg);
std::string error;
bool success = server->Serve(&error);
if (!success || error.empty() == false) {
@@ -418,22 +421,19 @@ static void __start_thread(void* arg)
}
}
-static void __shutdownThread(uv_async_t* arg)
-{
- auto server = reinterpret_cast<cmServerBase*>(arg->data);
- on_walk_to_shutdown(reinterpret_cast<uv_handle_t*>(arg), nullptr);
- server->StartShutDown();
-}
-
bool cmServerBase::StartServeThread()
{
ServeThreadRunning = true;
- uv_async_init(&Loop, &this->ShutdownSignal, __shutdownThread);
- this->ShutdownSignal.data = this;
uv_thread_create(&ServeThread, __start_thread, this);
return true;
}
+static void __shutdownThread(uv_async_t* arg)
+{
+ auto server = static_cast<cmServerBase*>(arg->data);
+ server->StartShutDown();
+}
+
bool cmServerBase::Serve(std::string* errorMessage)
{
#ifndef NDEBUG
@@ -444,26 +444,23 @@ bool cmServerBase::Serve(std::string* errorMessage)
errorMessage->clear();
- uv_signal_init(&Loop, &this->SIGINTHandler);
- uv_signal_init(&Loop, &this->SIGHUPHandler);
+ ShutdownSignal.init(Loop, __shutdownThread, this);
- this->SIGINTHandler.data = this;
- this->SIGHUPHandler.data = this;
+ SIGINTHandler.init(Loop, this);
+ SIGHUPHandler.init(Loop, this);
- uv_signal_start(&this->SIGINTHandler, &on_signal, SIGINT);
- uv_signal_start(&this->SIGHUPHandler, &on_signal, SIGHUP);
+ SIGINTHandler.start(&on_signal, SIGINT);
+ SIGHUPHandler.start(&on_signal, SIGHUP);
OnServeStart();
{
- uv_rwlock_rdlock(&ConnectionsMutex);
+ cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
for (auto& connection : Connections) {
if (!connection->OnServeStart(errorMessage)) {
- uv_rwlock_rdunlock(&ConnectionsMutex);
return false;
}
}
- uv_rwlock_rdunlock(&ConnectionsMutex);
}
if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
@@ -476,7 +473,6 @@ bool cmServerBase::Serve(std::string* errorMessage)
return false;
}
- ServeThreadRunning = false;
return true;
}
@@ -490,23 +486,16 @@ void cmServerBase::OnServeStart()
void cmServerBase::StartShutDown()
{
- if (!uv_is_closing(
- reinterpret_cast<const uv_handle_t*>(&this->SIGINTHandler))) {
- uv_signal_stop(&this->SIGINTHandler);
- }
-
- if (!uv_is_closing(
- reinterpret_cast<const uv_handle_t*>(&this->SIGHUPHandler))) {
- uv_signal_stop(&this->SIGHUPHandler);
- }
+ ShutdownSignal.reset();
+ SIGINTHandler.reset();
+ SIGHUPHandler.reset();
{
- uv_rwlock_wrlock(&ConnectionsMutex);
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
for (auto& connection : Connections) {
connection->OnConnectionShuttingDown();
}
Connections.clear();
- uv_rwlock_wrunlock(&ConnectionsMutex);
}
uv_walk(&Loop, on_walk_to_shutdown, nullptr);
@@ -523,31 +512,35 @@ cmServerBase::cmServerBase(cmConnection* connection)
{
auto err = uv_loop_init(&Loop);
(void)err;
- assert(err == 0);
-
- err = uv_rwlock_init(&ConnectionsMutex);
+ Loop.data = this;
assert(err == 0);
AddNewConnection(connection);
}
-cmServerBase::~cmServerBase()
+void cmServerBase::Close()
{
+ if (Loop.data) {
+ if (ServeThreadRunning) {
+ this->ShutdownSignal.send();
+ uv_thread_join(&ServeThread);
+ }
- if (ServeThreadRunning) {
- uv_async_send(&this->ShutdownSignal);
- uv_thread_join(&ServeThread);
+ uv_loop_close(&Loop);
+ Loop.data = nullptr;
}
-
- uv_loop_close(&Loop);
- uv_rwlock_destroy(&ConnectionsMutex);
+}
+cmServerBase::~cmServerBase()
+{
+ Close();
}
void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
{
- uv_rwlock_wrlock(&ConnectionsMutex);
- Connections.emplace_back(ownedConnection);
- uv_rwlock_wrunlock(&ConnectionsMutex);
+ {
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ Connections.emplace_back(ownedConnection);
+ }
ownedConnection->SetServer(this);
}
@@ -561,12 +554,14 @@ void cmServerBase::OnDisconnect(cmConnection* pConnection)
auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
return m.get() == pConnection;
};
- uv_rwlock_wrlock(&ConnectionsMutex);
- Connections.erase(
- std::remove_if(Connections.begin(), Connections.end(), pred),
- Connections.end());
- uv_rwlock_wrunlock(&ConnectionsMutex);
+ {
+ std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
+ Connections.erase(
+ std::remove_if(Connections.begin(), Connections.end(), pred),
+ Connections.end());
+ }
+
if (Connections.empty()) {
- StartShutDown();
+ this->ShutdownSignal.send();
}
}
diff --git a/Source/cmServer.h b/Source/cmServer.h
index 15fd2baee..ca37ce276 100644
--- a/Source/cmServer.h
+++ b/Source/cmServer.h
@@ -5,8 +5,11 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cm_jsoncpp_value.h"
+#include "cm_thread.hxx"
#include "cm_uv.h"
+#include "cmUVHandlePtr.h"
+
#include <memory> // IWYU pragma: keep
#include <string>
#include <vector>
@@ -57,16 +60,16 @@ public:
virtual bool OnSignal(int signum);
uv_loop_t* GetLoop();
-
+ void Close();
void OnDisconnect(cmConnection* pConnection);
protected:
- mutable uv_rwlock_t ConnectionsMutex;
+ mutable cm::shared_mutex ConnectionsMutex;
std::vector<std::unique_ptr<cmConnection>> Connections;
bool ServeThreadRunning = false;
uv_thread_t ServeThread;
- uv_async_t ShutdownSignal;
+ cm::uv_async_ptr ShutdownSignal;
#ifndef NDEBUG
public:
// When the server starts it will mark down it's current thread ID,
@@ -79,8 +82,8 @@ protected:
uv_loop_t Loop;
- uv_signal_t SIGINTHandler;
- uv_signal_t SIGHUPHandler;
+ cm::uv_signal_ptr SIGINTHandler;
+ cm::uv_signal_ptr SIGHUPHandler;
};
class cmServer : public cmServerBase
diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx
index 44af75f82..78c8f06bc 100644
--- a/Source/cmServerConnection.cxx
+++ b/Source/cmServerConnection.cxx
@@ -5,6 +5,9 @@
#include "cmConfigure.h"
#include "cmServer.h"
#include "cmServerDictionary.h"
+#include "cm_uv.h"
+
+#include <algorithm>
#ifdef _WIN32
#include "io.h"
#else
@@ -18,36 +21,34 @@ cmStdIoConnection::cmStdIoConnection(
{
}
-void cmStdIoConnection::SetupStream(uv_stream_t*& stream, int file_id)
+cm::uv_stream_ptr cmStdIoConnection::SetupStream(int file_id)
{
- assert(stream == nullptr);
switch (uv_guess_handle(file_id)) {
case UV_TTY: {
- auto tty = new uv_tty_t();
- uv_tty_init(this->Server->GetLoop(), tty, file_id, file_id == 0);
+ cm::uv_tty_ptr tty;
+ tty.init(*this->Server->GetLoop(), file_id, file_id == 0,
+ static_cast<cmEventBasedConnection*>(this));
uv_tty_set_mode(tty, UV_TTY_MODE_NORMAL);
- stream = reinterpret_cast<uv_stream_t*>(tty);
- break;
+ return std::move(tty);
}
case UV_FILE:
if (file_id == 0) {
- return;
+ return nullptr;
}
// Intentional fallthrough; stdin can _not_ be treated as a named
// pipe, however stdout can be.
CM_FALLTHROUGH;
case UV_NAMED_PIPE: {
- auto pipe = new uv_pipe_t();
- uv_pipe_init(this->Server->GetLoop(), pipe, 0);
+ cm::uv_pipe_ptr pipe;
+ pipe.init(*this->Server->GetLoop(), 0,
+ static_cast<cmEventBasedConnection*>(this));
uv_pipe_open(pipe, file_id);
- stream = reinterpret_cast<uv_stream_t*>(pipe);
- break;
+ return std::move(pipe);
}
default:
assert(false && "Unable to determine stream type");
- return;
+ return nullptr;
}
- stream->data = static_cast<cmEventBasedConnection*>(this);
}
void cmStdIoConnection::SetServer(cmServerBase* s)
@@ -57,14 +58,14 @@ void cmStdIoConnection::SetServer(cmServerBase* s)
return;
}
- SetupStream(this->ReadStream, 0);
- SetupStream(this->WriteStream, 1);
+ this->ReadStream = SetupStream(0);
+ this->WriteStream = SetupStream(1);
}
void shutdown_connection(uv_prepare_t* prepare)
{
cmStdIoConnection* connection =
- reinterpret_cast<cmStdIoConnection*>(prepare->data);
+ static_cast<cmStdIoConnection*>(prepare->data);
if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(prepare))) {
uv_close(reinterpret_cast<uv_handle_t*>(prepare),
@@ -76,7 +77,7 @@ void shutdown_connection(uv_prepare_t* prepare)
bool cmStdIoConnection::OnServeStart(std::string* pString)
{
Server->OnConnected(this);
- if (this->ReadStream) {
+ if (this->ReadStream.get()) {
uv_read_start(this->ReadStream, on_alloc_buffer, on_read);
} else if (uv_guess_handle(0) == UV_FILE) {
char buffer[1024];
@@ -94,44 +95,14 @@ bool cmStdIoConnection::OnServeStart(std::string* pString)
return cmConnection::OnServeStart(pString);
}
-void cmStdIoConnection::ShutdownStream(uv_stream_t*& stream)
-{
- if (!stream) {
- return;
- }
- switch (stream->type) {
- case UV_TTY: {
- assert(!uv_is_closing(reinterpret_cast<uv_handle_t*>(stream)));
- if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(stream))) {
- uv_close(reinterpret_cast<uv_handle_t*>(stream),
- &on_close_delete<uv_tty_t>);
- }
- break;
- }
- case UV_FILE:
- case UV_NAMED_PIPE: {
- assert(!uv_is_closing(reinterpret_cast<uv_handle_t*>(stream)));
- if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(stream))) {
- uv_close(reinterpret_cast<uv_handle_t*>(stream),
- &on_close_delete<uv_pipe_t>);
- }
- break;
- }
- default:
- assert(false && "Unable to determine stream type");
- }
-
- stream = nullptr;
-}
-
bool cmStdIoConnection::OnConnectionShuttingDown()
{
- if (ReadStream) {
+ if (ReadStream.get()) {
uv_read_stop(ReadStream);
+ ReadStream->data = nullptr;
}
- ShutdownStream(ReadStream);
- ShutdownStream(WriteStream);
+ this->ReadStream.reset();
cmEventBasedConnection::OnConnectionShuttingDown();
diff --git a/Source/cmServerConnection.h b/Source/cmServerConnection.h
index 4ca908ddf..a70edb4b5 100644
--- a/Source/cmServerConnection.h
+++ b/Source/cmServerConnection.h
@@ -8,7 +8,7 @@
#include "cmConnection.h"
#include "cmPipeConnection.h"
-#include "cm_uv.h"
+#include "cmUVHandlePtr.h"
class cmServerBase;
@@ -46,8 +46,8 @@ public:
bool OnServeStart(std::string* pString) override;
private:
- void SetupStream(uv_stream_t*& stream, int file_id);
- void ShutdownStream(uv_stream_t*& stream);
+ cm::uv_stream_ptr SetupStream(int file_id);
+ cm::uv_stream_ptr ReadStream;
};
/***
diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h
index e6a7ae6ca..685542c14 100644
--- a/Source/cmServerDictionary.h
+++ b/Source/cmServerDictionary.h
@@ -23,6 +23,7 @@ static const std::string kPROGRESS_TYPE = "progress";
static const std::string kREPLY_TYPE = "reply";
static const std::string kSET_GLOBAL_SETTINGS_TYPE = "setGlobalSettings";
static const std::string kSIGNAL_TYPE = "signal";
+static const std::string kCTEST_INFO_TYPE = "ctestInfo";
static const std::string kARTIFACTS_KEY = "artifacts";
static const std::string kBUILD_DIRECTORY_KEY = "buildDirectory";
@@ -88,6 +89,13 @@ static const std::string kWARN_UNUSED_CLI_KEY = "warnUnusedCli";
static const std::string kWARN_UNUSED_KEY = "warnUnused";
static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories";
static const std::string kWATCHED_FILES_KEY = "watchedFiles";
+static const std::string kHAS_INSTALL_RULE = "hasInstallRule";
+static const std::string kINSTALL_PATHS = "installPaths";
+static const std::string kCTEST_NAME = "ctestName";
+static const std::string kCTEST_COMMAND = "ctestCommand";
+static const std::string kCTEST_INFO = "ctestInfo";
+static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion";
+static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided";
static const std::string kSTART_MAGIC = "[== \"CMake Server\" ==[";
static const std::string kEND_MAGIC = "]== \"CMake Server\" ==]";
diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx
index 13b18c24c..7c10110b1 100644
--- a/Source/cmServerProtocol.cxx
+++ b/Source/cmServerProtocol.cxx
@@ -8,9 +8,12 @@
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
+#include "cmInstallGenerator.h"
+#include "cmInstallTargetGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmProperty.h"
#include "cmServer.h"
#include "cmServerDictionary.h"
#include "cmSourceFile.h"
@@ -19,6 +22,8 @@
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
+#include "cmTarget.h"
+#include "cmTest.h"
#include "cm_uv.h"
#include "cmake.h"
@@ -28,6 +33,7 @@
#include <functional>
#include <limits>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <unordered_map>
@@ -97,7 +103,7 @@ void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir,
std::string toAdd = lf;
if (!sourceDir.empty()) {
const std::string& relative =
- cmSystemTools::RelativePath(sourceDir.c_str(), lf.c_str());
+ cmSystemTools::RelativePath(sourceDir, lf);
if (toAdd.size() > relative.size()) {
toAdd = relative;
}
@@ -105,16 +111,16 @@ void getCMakeInputs(const cmGlobalGenerator* gg, const std::string& sourceDir,
if (isInternal) {
if (internalFiles) {
- internalFiles->push_back(toAdd);
+ internalFiles->push_back(std::move(toAdd));
}
} else {
if (isTemporary) {
if (tmpFiles) {
- tmpFiles->push_back(toAdd);
+ tmpFiles->push_back(std::move(toAdd));
}
} else {
if (explicitFiles) {
- explicitFiles->push_back(toAdd);
+ explicitFiles->push_back(std::move(toAdd));
}
}
}
@@ -250,7 +256,7 @@ bool cmServerProtocol::DoActivate(const cmServerRequest& /*request*/,
std::pair<int, int> cmServerProtocol1::ProtocolVersion() const
{
- return std::make_pair(1, 1);
+ return std::make_pair(1, 2);
}
static void setErrorMessage(std::string* errorMessage, const std::string& text)
@@ -260,8 +266,8 @@ static void setErrorMessage(std::string* errorMessage, const std::string& text)
}
}
-static bool testHomeDirectory(cmState* state, std::string& value,
- std::string* errorMessage)
+static bool getOrTestHomeDirectory(cmState* state, std::string& value,
+ std::string* errorMessage)
{
const std::string cachedValue =
std::string(state->GetCacheEntryValue("CMAKE_HOME_DIRECTORY"));
@@ -282,9 +288,10 @@ static bool testHomeDirectory(cmState* state, std::string& value,
return true;
}
-static bool testValue(cmState* state, const std::string& key,
- std::string& value, const std::string& keyDescription,
- std::string* errorMessage)
+static bool getOrTestValue(cmState* state, const std::string& key,
+ std::string& value,
+ const std::string& keyDescription,
+ std::string* errorMessage)
{
const char* entry = state->GetCacheEntryValue(key);
const std::string cachedValue =
@@ -331,31 +338,31 @@ bool cmServerProtocol1::DoActivate(const cmServerRequest& request,
cmState* state = cm->GetState();
// Check generator:
- if (!testValue(state, "CMAKE_GENERATOR", generator, "generator",
- errorMessage)) {
+ if (!getOrTestValue(state, "CMAKE_GENERATOR", generator, "generator",
+ errorMessage)) {
return false;
}
// check extra generator:
- if (!testValue(state, "CMAKE_EXTRA_GENERATOR", extraGenerator,
- "extra generator", errorMessage)) {
+ if (!getOrTestValue(state, "CMAKE_EXTRA_GENERATOR", extraGenerator,
+ "extra generator", errorMessage)) {
return false;
}
// check sourcedir:
- if (!testHomeDirectory(state, sourceDirectory, errorMessage)) {
+ if (!getOrTestHomeDirectory(state, sourceDirectory, errorMessage)) {
return false;
}
// check toolset:
- if (!testValue(state, "CMAKE_GENERATOR_TOOLSET", toolset, "toolset",
- errorMessage)) {
+ if (!getOrTestValue(state, "CMAKE_GENERATOR_TOOLSET", toolset, "toolset",
+ errorMessage)) {
return false;
}
// check platform:
- if (!testValue(state, "CMAKE_GENERATOR_PLATFORM", platform, "platform",
- errorMessage)) {
+ if (!getOrTestValue(state, "CMAKE_GENERATOR_PLATFORM", platform,
+ "platform", errorMessage)) {
return false;
}
}
@@ -474,6 +481,9 @@ const cmServerResponse cmServerProtocol1::Process(
if (request.Type == kSET_GLOBAL_SETTINGS_TYPE) {
return this->ProcessSetGlobalSettings(request);
}
+ if (request.Type == kCTEST_INFO_TYPE) {
+ return this->ProcessCTests(request);
+ }
return request.ReportError("Unknown command!");
}
@@ -538,8 +548,8 @@ cmServerResponse cmServerProtocol1::ProcessCMakeInputs(
const cmake* cm = this->CMakeInstance();
const cmGlobalGenerator* gg = cm->GetGlobalGenerator();
const std::string cmakeRootDir = cmSystemTools::GetCMakeRoot();
- const std::string buildDir = cm->GetHomeOutputDirectory();
- const std::string sourceDir = cm->GetHomeDirectory();
+ const std::string& buildDir = cm->GetHomeOutputDirectory();
+ const std::string& sourceDir = cm->GetHomeDirectory();
Json::Value result = Json::objectValue;
result[kSOURCE_DIRECTORY_KEY] = sourceDir;
@@ -665,8 +675,7 @@ static Json::Value DumpSourceFileGroup(const LanguageData& data,
Json::Value sourcesValue = Json::arrayValue;
for (auto const& i : files) {
- const std::string relPath =
- cmSystemTools::RelativePath(baseDir.c_str(), i.c_str());
+ const std::string relPath = cmSystemTools::RelativePath(baseDir, i);
sourcesValue.append(relPath.size() < i.size() ? relPath : i);
}
@@ -690,24 +699,56 @@ static Json::Value DumpSourceFilesList(
if (!fileData.Language.empty()) {
const LanguageData& ld = languageDataMap.at(fileData.Language);
cmLocalGenerator* lg = target->GetLocalGenerator();
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ lg, target, config, target->GetName(), fileData.Language);
std::string compileFlags = ld.Flags;
- if (const char* cflags = file->GetProperty("COMPILE_FLAGS")) {
- cmGeneratorExpression ge;
- auto cge = ge.Parse(cflags);
- const char* processed =
- cge->Evaluate(target->GetLocalGenerator(), config);
- lg->AppendFlags(compileFlags, processed);
+ const std::string COMPILE_FLAGS("COMPILE_FLAGS");
+ if (const char* cflags = file->GetProperty(COMPILE_FLAGS)) {
+ lg->AppendFlags(compileFlags,
+ genexInterpreter.Evaluate(cflags, COMPILE_FLAGS));
+ }
+ const std::string COMPILE_OPTIONS("COMPILE_OPTIONS");
+ if (const char* coptions = file->GetProperty(COMPILE_OPTIONS)) {
+ lg->AppendCompileOptions(
+ compileFlags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS));
}
fileData.Flags = compileFlags;
- fileData.IncludePathList = ld.IncludePathList;
+ // Add include directories from source file properties.
+ std::vector<std::string> includes;
+
+ const std::string INCLUDE_DIRECTORIES("INCLUDE_DIRECTORIES");
+ if (const char* cincludes = file->GetProperty(INCLUDE_DIRECTORIES)) {
+ const char* evaluatedIncludes =
+ genexInterpreter.Evaluate(cincludes, INCLUDE_DIRECTORIES);
+ lg->AppendIncludeDirectories(includes, evaluatedIncludes, *file);
+
+ for (const auto& include : includes) {
+ fileData.IncludePathList.push_back(
+ std::make_pair(include, target->IsSystemIncludeDirectory(
+ include, config, fileData.Language)));
+ }
+ }
+
+ fileData.IncludePathList.insert(fileData.IncludePathList.end(),
+ ld.IncludePathList.begin(),
+ ld.IncludePathList.end());
+ const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS");
std::set<std::string> defines;
- lg->AppendDefines(defines, file->GetProperty("COMPILE_DEFINITIONS"));
+ if (const char* defs = file->GetProperty(COMPILE_DEFINITIONS)) {
+ lg->AppendDefines(
+ defines, genexInterpreter.Evaluate(defs, COMPILE_DEFINITIONS));
+ }
+
const std::string defPropName =
"COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config);
- lg->AppendDefines(defines, file->GetProperty(defPropName));
+ if (const char* config_defs = file->GetProperty(defPropName)) {
+ lg->AppendDefines(defines, genexInterpreter.Evaluate(
+ config_defs, COMPILE_DEFINITIONS));
+ }
+
defines.insert(ld.Defines.begin(), ld.Defines.end());
fileData.SetDefines(defines);
@@ -730,6 +771,108 @@ static Json::Value DumpSourceFilesList(
return result;
}
+static Json::Value DumpCTestInfo(cmLocalGenerator* lg, cmTest* testInfo,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kCTEST_NAME] = testInfo->GetName();
+
+ // Concat command entries together. After the first should be the arguments
+ // for the command
+ std::string command;
+ for (auto const& cmd : testInfo->GetCommand()) {
+ command.append(cmd);
+ command.append(" ");
+ }
+
+ // Remove any config specific variables from the output.
+ cmGeneratorExpression ge;
+ auto cge = ge.Parse(command.c_str());
+ const char* processed = cge->Evaluate(lg, config);
+
+ result[kCTEST_COMMAND] = processed;
+
+ // Build up the list of properties that may have been specified
+ Json::Value properties = Json::arrayValue;
+ for (auto& prop : testInfo->GetProperties()) {
+ Json::Value entry = Json::objectValue;
+ entry[kKEY_KEY] = prop.first;
+
+ // Remove config variables from the value too.
+ auto cge_value = ge.Parse(prop.second.GetValue());
+ const char* processed_value = cge_value->Evaluate(lg, config);
+ entry[kVALUE_KEY] = processed_value;
+ properties.append(entry);
+ }
+ result[kPROPERTIES_KEY] = properties;
+
+ return result;
+}
+
+static void DumpMakefileTests(cmLocalGenerator* lg, const std::string& config,
+ Json::Value* result)
+{
+ auto mf = lg->GetMakefile();
+ std::vector<cmTest*> tests;
+ mf->GetTests(config, tests);
+ for (auto test : tests) {
+ Json::Value tmp = DumpCTestInfo(lg, test, config);
+ if (!tmp.isNull()) {
+ result->append(tmp);
+ }
+ }
+}
+
+static Json::Value DumpCTestProjectList(const cmake* cm,
+ std::string const& config)
+{
+ Json::Value result = Json::arrayValue;
+
+ auto globalGen = cm->GetGlobalGenerator();
+
+ for (const auto& projectIt : globalGen->GetProjectMap()) {
+ Json::Value pObj = Json::objectValue;
+ pObj[kNAME_KEY] = projectIt.first;
+
+ Json::Value tests = Json::arrayValue;
+
+ // Gather tests for every generator
+ for (const auto& lg : projectIt.second) {
+ // Make sure they're generated.
+ lg->GenerateTestFiles();
+ DumpMakefileTests(lg, config, &tests);
+ }
+
+ pObj[kCTEST_INFO] = tests;
+
+ result.append(pObj);
+ }
+
+ return result;
+}
+
+static Json::Value DumpCTestConfiguration(const cmake* cm,
+ const std::string& config)
+{
+ Json::Value result = Json::objectValue;
+ result[kNAME_KEY] = config;
+
+ result[kPROJECTS_KEY] = DumpCTestProjectList(cm, config);
+
+ return result;
+}
+
+static Json::Value DumpCTestConfigurationsList(const cmake* cm)
+{
+ Json::Value result = Json::arrayValue;
+
+ for (const std::string& c : getConfigurations(cm)) {
+ result.append(DumpCTestConfiguration(cm, c));
+ }
+
+ return result;
+}
+
static Json::Value DumpTarget(cmGeneratorTarget* target,
const std::string& config)
{
@@ -754,6 +897,8 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
Json::Value result = Json::objectValue;
result[kNAME_KEY] = target->GetName();
+ result[kIS_GENERATOR_PROVIDED_KEY] =
+ target->Target->GetIsGeneratorProvided();
result[kTYPE_KEY] = typeName;
result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory();
result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory();
@@ -764,6 +909,34 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
result[kFULL_NAME_KEY] = target->GetFullName(config);
+ if (target->Target->GetHaveInstallRule()) {
+ result[kHAS_INSTALL_RULE] = true;
+
+ Json::Value installPaths = Json::arrayValue;
+ auto targetGenerators = target->Makefile->GetInstallGenerators();
+ for (auto installGenerator : targetGenerators) {
+ auto installTargetGenerator =
+ dynamic_cast<cmInstallTargetGenerator*>(installGenerator);
+ if (installTargetGenerator != nullptr &&
+ installTargetGenerator->GetTarget()->Target == target->Target) {
+ auto dest = installTargetGenerator->GetDestination(config);
+
+ std::string installPath;
+ if (!dest.empty() && cmSystemTools::FileIsFullPath(dest)) {
+ installPath = dest;
+ } else {
+ std::string installPrefix =
+ target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX");
+ installPath = installPrefix + '/' + dest;
+ }
+
+ installPaths.append(installPath);
+ }
+ }
+
+ result[kINSTALL_PATHS] = installPaths;
+ }
+
if (target->HaveWellDefinedOutputFiles()) {
Json::Value artifacts = Json::arrayValue;
artifacts.append(
@@ -833,7 +1006,7 @@ static Json::Value DumpTarget(cmGeneratorTarget* target,
lg->GetIncludeDirectories(includePathList, target, lang, config, true);
for (std::string const& i : includePathList) {
ld.IncludePathList.push_back(
- std::make_pair(i, target->IsSystemIncludeDirectory(i, config)));
+ std::make_pair(i, target->IsSystemIncludeDirectory(i, config, lang)));
}
}
@@ -884,10 +1057,26 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config)
// Project structure information:
const cmMakefile* mf = lg->GetMakefile();
+ auto minVersion = mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
+ pObj[kMINIMUM_CMAKE_VERSION] = minVersion ? minVersion : "";
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);
}
@@ -1141,6 +1330,19 @@ cmServerResponse cmServerProtocol1::ProcessFileSystemWatchers(
return request.Reply(result);
}
+cmServerResponse cmServerProtocol1::ProcessCTests(
+ const cmServerRequest& request)
+{
+ if (this->m_State < STATE_COMPUTED) {
+ return request.ReportError("This instance was not yet computed.");
+ }
+
+ Json::Value result = Json::objectValue;
+ result[kCONFIGURATIONS_KEY] =
+ DumpCTestConfigurationsList(this->CMakeInstance());
+ return request.Reply(result);
+}
+
cmServerProtocol1::GeneratorInformation::GeneratorInformation(
const std::string& generatorName, const std::string& extraGeneratorName,
const std::string& toolset, const std::string& platform,
diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h
index 124ac7f67..df71cffc7 100644
--- a/Source/cmServerProtocol.h
+++ b/Source/cmServerProtocol.h
@@ -123,6 +123,7 @@ private:
cmServerResponse ProcessGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessSetGlobalSettings(const cmServerRequest& request);
cmServerResponse ProcessFileSystemWatchers(const cmServerRequest& request);
+ cmServerResponse ProcessCTests(const cmServerRequest& request);
enum State
{
diff --git a/Source/cmSetCommand.cxx b/Source/cmSetCommand.cxx
index b32cda3cd..985aac80f 100644
--- a/Source/cmSetCommand.cxx
+++ b/Source/cmSetCommand.cxx
@@ -2,8 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSetCommand.h"
-#include <string.h>
-
#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmState.h"
@@ -22,19 +20,15 @@ bool cmSetCommand::InitialPass(std::vector<std::string> const& args,
}
// watch for ENV signatures
- const char* variable = args[0].c_str(); // VAR is always first
- if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
+ auto const& variable = args[0]; // VAR is always first
+ if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) {
// what is the variable name
- char* varName = new char[strlen(variable)];
- strncpy(varName, variable + 4, strlen(variable) - 5);
- varName[strlen(variable) - 5] = '\0';
- std::string putEnvArg = varName;
- putEnvArg += "=";
+ auto const& varName = variable.substr(4, variable.size() - 5);
+ std::string putEnvArg = varName + "=";
// what is the current value if any
std::string currValue;
const bool currValueSet = cmSystemTools::GetEnv(varName, currValue);
- delete[] varName;
// will it be set to something, then set it
if (args.size() > 1 && !args[1].empty()) {
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 7efcc0403..171b62e46 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -167,7 +167,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode()
// Construct the directory name. Interpret relative paths with
// respect to the current directory.
std::string dir = *this->Names.begin();
- if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(dir)) {
dir = this->Makefile->GetCurrentSourceDirectory();
dir += "/";
dir += *this->Names.begin();
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 0964bea6b..6792d6638 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -12,8 +12,9 @@
#include "cmSystemTools.h"
#include "cmake.h"
-cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name)
- : Location(mf, name)
+cmSourceFile::cmSourceFile(cmMakefile* mf, const std::string& name,
+ cmSourceFileLocationKind kind)
+ : Location(mf, name, kind)
{
this->CustomCommand = nullptr;
this->FindFullPathFailed = false;
@@ -110,7 +111,7 @@ std::string const& cmSourceFile::GetFullPath() const
bool cmSourceFile::FindFullPath(std::string* error)
{
- // If thie method has already failed once do not try again.
+ // If this method has already failed once do not try again.
if (this->FindFullPathFailed) {
return false;
}
@@ -191,7 +192,7 @@ bool cmSourceFile::TryFullPath(const std::string& path, const std::string& ext)
tryPath += ".";
tryPath += ext;
}
- if (cmSystemTools::FileExists(tryPath.c_str())) {
+ if (cmSystemTools::FileExists(tryPath)) {
this->FullPath = tryPath;
return true;
}
diff --git a/Source/cmSourceFile.h b/Source/cmSourceFile.h
index c2105d224..1516d98ed 100644
--- a/Source/cmSourceFile.h
+++ b/Source/cmSourceFile.h
@@ -7,6 +7,7 @@
#include "cmPropertyMap.h"
#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include <string>
#include <vector>
@@ -27,7 +28,9 @@ public:
* Construct with the makefile storing the source and the initial
* name referencing it.
*/
- cmSourceFile(cmMakefile* mf, const std::string& name);
+ cmSourceFile(
+ cmMakefile* mf, const std::string& name,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
~cmSourceFile();
@@ -120,7 +123,8 @@ private:
#define CM_HEADER_REGEX "\\.(h|hh|h\\+\\+|hm|hpp|hxx|in|txx|inl)$"
#define CM_SOURCE_REGEX \
- "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|hpj" \
+ "\\.(C|M|c|c\\+\\+|cc|cpp|cxx|cu|f|f90|for|fpp|ftn|m|mm|rc|def|r|odl|idl|" \
+ "hpj" \
"|bat)$"
#define CM_RESOURCE_REGEX "\\.(pdf|plist|png|jpeg|jpg|storyboard|xcassets)$"
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 4f337f246..bd8d318d7 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)
@@ -29,17 +27,23 @@ cmSourceFileLocation::cmSourceFileLocation(const cmSourceFileLocation& loc)
}
cmSourceFileLocation::cmSourceFileLocation(cmMakefile const* mf,
- const std::string& name)
+ const std::string& name,
+ cmSourceFileLocationKind kind)
: Makefile(mf)
{
- this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name.c_str());
+ this->AmbiguousDirectory = !cmSystemTools::FileIsFullPath(name);
this->AmbiguousExtension = true;
this->Directory = cmSystemTools::GetFilenamePath(name);
- if (cmSystemTools::FileIsFullPath(this->Directory.c_str())) {
+ if (cmSystemTools::FileIsFullPath(this->Directory)) {
this->Directory = cmSystemTools::CollapseFullPath(this->Directory);
}
this->Name = cmSystemTools::GetFilenameName(name);
- this->UpdateExtension(name);
+ if (kind == cmSourceFileLocationKind::Known) {
+ this->DirectoryUseSource();
+ this->AmbiguousExtension = false;
+ } else {
+ this->UpdateExtension(name);
+ }
}
void cmSourceFileLocation::Update(cmSourceFileLocation const& loc)
@@ -86,13 +90,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;
@@ -112,7 +112,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
tryPath += "/";
}
tryPath += this->Name;
- if (cmSystemTools::FileExists(tryPath.c_str(), true)) {
+ if (cmSystemTools::FileExists(tryPath, true)) {
// We found a source file named by the user on disk. Trust it's
// extension.
this->Name = cmSystemTools::GetFilenameName(name);
@@ -149,14 +149,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/cmSourceFileLocation.h b/Source/cmSourceFileLocation.h
index 467682db9..f325e547a 100644
--- a/Source/cmSourceFileLocation.h
+++ b/Source/cmSourceFileLocation.h
@@ -7,6 +7,8 @@
#include <string>
+#include "cmSourceFileLocationKind.h"
+
class cmMakefile;
/** \class cmSourceFileLocation
@@ -26,7 +28,9 @@ public:
* Construct for a source file created in a given cmMakefile
* instance with an initial name.
*/
- cmSourceFileLocation(cmMakefile const* mf, const std::string& name);
+ cmSourceFileLocation(
+ cmMakefile const* mf, const std::string& name,
+ cmSourceFileLocationKind kind = cmSourceFileLocationKind::Ambiguous);
cmSourceFileLocation();
cmSourceFileLocation(const cmSourceFileLocation& loc);
@@ -38,12 +42,12 @@ public:
bool Matches(cmSourceFileLocation const& loc);
/**
- * Explicity state that the source file is located in the source tree.
+ * Explicitly state that the source file is located in the source tree.
*/
void DirectoryUseSource();
/**
- * Explicity state that the source file is located in the build tree.
+ * Explicitly state that the source file is located in the build tree.
*/
void DirectoryUseBinary();
diff --git a/Source/cmSourceFileLocationKind.h b/Source/cmSourceFileLocationKind.h
new file mode 100644
index 000000000..dd4c6dd4f
--- /dev/null
+++ b/Source/cmSourceFileLocationKind.h
@@ -0,0 +1,15 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef cmSourceFileLocationKind_h
+#define cmSourceFileLocationKind_h
+
+enum class cmSourceFileLocationKind
+{
+ // The location is user-specified and may be ambiguous.
+ Ambiguous,
+ // The location is known to be at the given location; do not try to guess at
+ // extensions or absolute path.
+ Known
+};
+
+#endif
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index fba4c31d3..12ef62bc2 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -8,7 +8,7 @@ public:
std::vector<cmSourceGroup> GroupChildren;
};
-cmSourceGroup::cmSourceGroup(const char* name, const char* regex,
+cmSourceGroup::cmSourceGroup(const std::string& name, const char* regex,
const char* parentName)
: Name(name)
{
@@ -60,24 +60,24 @@ 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)
+bool cmSourceGroup::MatchesRegex(const std::string& name)
{
return this->GroupRegex.find(name);
}
-bool cmSourceGroup::MatchesFiles(const char* name)
+bool cmSourceGroup::MatchesFiles(const std::string& name) const
{
- return this->GroupFiles.find(name) != this->GroupFiles.end();
+ return this->GroupFiles.find(name) != this->GroupFiles.cend();
}
void cmSourceGroup::AssignSource(const cmSourceFile* sf)
@@ -95,21 +95,12 @@ void cmSourceGroup::AddChild(cmSourceGroup const& child)
this->Internal->GroupChildren.push_back(child);
}
-cmSourceGroup* cmSourceGroup::LookupChild(const char* name) const
+cmSourceGroup* cmSourceGroup::LookupChild(const std::string& name)
{
- // initializing iterators
- std::vector<cmSourceGroup>::const_iterator iter =
- this->Internal->GroupChildren.begin();
- const std::vector<cmSourceGroup>::const_iterator end =
- this->Internal->GroupChildren.end();
-
- // st
- for (; iter != end; ++iter) {
- std::string sgName = iter->GetName();
-
+ for (cmSourceGroup& group : this->Internal->GroupChildren) {
// look if descenened is the one were looking for
- if (sgName == name) {
- return const_cast<cmSourceGroup*>(&(*iter)); // if it so return it
+ if (group.GetName() == name) {
+ return (&group); // if it so return it
}
}
@@ -117,19 +108,13 @@ cmSourceGroup* cmSourceGroup::LookupChild(const char* name) const
return nullptr;
}
-cmSourceGroup* cmSourceGroup::MatchChildrenFiles(const char* name)
+cmSourceGroup* cmSourceGroup::MatchChildrenFiles(const std::string& name)
{
- // initializing iterators
- std::vector<cmSourceGroup>::iterator iter =
- this->Internal->GroupChildren.begin();
- std::vector<cmSourceGroup>::iterator end =
- this->Internal->GroupChildren.end();
-
if (this->MatchesFiles(name)) {
return this;
}
- for (; iter != end; ++iter) {
- cmSourceGroup* result = iter->MatchChildrenFiles(name);
+ for (cmSourceGroup& group : this->Internal->GroupChildren) {
+ cmSourceGroup* result = group.MatchChildrenFiles(name);
if (result) {
return result;
}
@@ -137,16 +122,10 @@ cmSourceGroup* cmSourceGroup::MatchChildrenFiles(const char* name)
return nullptr;
}
-cmSourceGroup* cmSourceGroup::MatchChildrenRegex(const char* name)
+cmSourceGroup* cmSourceGroup::MatchChildrenRegex(const std::string& name)
{
- // initializing iterators
- std::vector<cmSourceGroup>::iterator iter =
- this->Internal->GroupChildren.begin();
- std::vector<cmSourceGroup>::iterator end =
- this->Internal->GroupChildren.end();
-
- for (; iter != end; ++iter) {
- cmSourceGroup* result = iter->MatchChildrenRegex(name);
+ for (cmSourceGroup& group : this->Internal->GroupChildren) {
+ cmSourceGroup* result = group.MatchChildrenRegex(name);
if (result) {
return result;
}
diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h
index e8bd69767..b39f8ddb1 100644
--- a/Source/cmSourceGroup.h
+++ b/Source/cmSourceGroup.h
@@ -26,7 +26,7 @@ class cmSourceGroupInternals;
class cmSourceGroup
{
public:
- cmSourceGroup(const char* name, const char* regex,
+ cmSourceGroup(const std::string& name, const char* regex,
const char* parentName = nullptr);
cmSourceGroup(cmSourceGroup const& r);
~cmSourceGroup();
@@ -50,38 +50,38 @@ public:
/**
* Looks up child and returns it
*/
- cmSourceGroup* LookupChild(const char* name) const;
+ cmSourceGroup* LookupChild(const std::string& name);
/**
* 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.
*/
- bool MatchesRegex(const char* name);
+ bool MatchesRegex(const std::string& name);
/**
* Check if the given name matches this group's explicit file list.
*/
- bool MatchesFiles(const char* name);
+ bool MatchesFiles(const std::string& name) const;
/**
* Check if the given name matches this group's explicit file list
* in children.
*/
- cmSourceGroup* MatchChildrenFiles(const char* name);
+ cmSourceGroup* MatchChildrenFiles(const std::string& name);
/**
* Check if the given name matches this group's regex in children.
*/
- cmSourceGroup* MatchChildrenRegex(const char* name);
+ cmSourceGroup* MatchChildrenRegex(const std::string& name);
/**
* Assign the given source file to this group. Used only by
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 69983a875..8c9b63c6a 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -2,19 +2,21 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmSourceGroupCommand.h"
+#include <algorithm>
#include <set>
-#include <sstream>
#include <stddef.h>
+#include <utility>
#include "cmMakefile.h"
#include "cmSourceGroup.h"
#include "cmSystemTools.h"
namespace {
-const size_t RootIndex = 1;
-const size_t FilesWithoutPrefixKeywordIndex = 2;
-const size_t FilesWithPrefixKeywordIndex = 4;
-const size_t PrefixKeywordIndex = 2;
+const std::string kTreeOptionName = "TREE";
+const std::string kPrefixOptionName = "PREFIX";
+const std::string kFilesOptionName = "FILES";
+const std::string kRegexOptionName = "REGULAR_EXPRESSION";
+const std::string kSourceGroupOptionName = "<sg_name>";
std::vector<std::string> tokenizePath(const std::string& path)
{
@@ -26,7 +28,7 @@ std::string getFullFilePath(const std::string& currentPath,
{
std::string fullPath = path;
- if (!cmSystemTools::FileIsFullPath(path.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(path)) {
fullPath = currentPath;
fullPath += "/";
fullPath += path;
@@ -71,14 +73,13 @@ std::string prepareFilePathForTree(const std::string& path,
}
std::vector<std::string> prepareFilesPathsForTree(
- std::vector<std::string>::const_iterator begin,
- std::vector<std::string>::const_iterator end,
+ const std::vector<std::string>& filesPaths,
const std::string& currentSourceDir)
{
std::vector<std::string> prepared;
- for (; begin != end; ++begin) {
- prepared.push_back(prepareFilePathForTree(*begin, currentSourceDir));
+ for (auto const& filePath : filesPaths) {
+ prepared.push_back(prepareFilePathForTree(filePath, currentSourceDir));
}
return prepared;
@@ -121,6 +122,57 @@ bool addFilesToItsSourceGroups(const std::string& root,
class cmExecutionStatus;
// cmSourceGroupCommand
+cmSourceGroupCommand::ExpectedOptions
+cmSourceGroupCommand::getExpectedOptions() const
+{
+ ExpectedOptions options;
+
+ options.push_back(kTreeOptionName);
+ options.push_back(kPrefixOptionName);
+ options.push_back(kFilesOptionName);
+ options.push_back(kRegexOptionName);
+
+ return options;
+}
+
+bool cmSourceGroupCommand::isExpectedOption(
+ const std::string& argument, const ExpectedOptions& expectedOptions)
+{
+ return std::find(expectedOptions.begin(), expectedOptions.end(), argument) !=
+ expectedOptions.end();
+}
+
+void cmSourceGroupCommand::parseArguments(
+ const std::vector<std::string>& args,
+ cmSourceGroupCommand::ParsedArguments& parsedArguments)
+{
+ const ExpectedOptions expectedOptions = getExpectedOptions();
+ size_t i = 0;
+
+ // at this point we know that args vector is not empty
+
+ // if first argument is not one of expected options it's source group name
+ if (!isExpectedOption(args[0], expectedOptions)) {
+ // get source group name and go to next argument
+ parsedArguments[kSourceGroupOptionName].push_back(args[0]);
+ ++i;
+ }
+
+ for (; i < args.size();) {
+ // get current option and increment index to go to next argument
+ const std::string& currentOption = args[i++];
+
+ // create current option entry in parsed arguments
+ std::vector<std::string>& currentOptionArguments =
+ parsedArguments[currentOption];
+
+ // collect option arguments while we won't find another expected option
+ while (i < args.size() && !isExpectedOption(args[i], expectedOptions)) {
+ currentOptionArguments.push_back(args[i++]);
+ }
+ }
+}
+
bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
@@ -129,114 +181,98 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- if (args[0] == "TREE") {
- std::string error;
+ // If only two arguments are given, the pre-1.8 version of the
+ // command is being invoked.
+ if (args.size() == 2 && args[1] != "FILES") {
+ cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]);
- if (!processTree(args, error)) {
- this->SetError(error);
+ if (!sg) {
+ this->SetError("Could not create or find source group");
return false;
}
+ sg->SetGroupRegex(args[1].c_str());
return true;
}
- cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]);
+ ParsedArguments parsedArguments;
+ std::string errorMsg;
+
+ parseArguments(args, parsedArguments);
- if (!sg) {
- this->SetError("Could not create or find source group");
+ if (!checkArgumentsPreconditions(parsedArguments, errorMsg)) {
return false;
}
- // If only two arguments are given, the pre-1.8 version of the
- // command is being invoked.
- if (args.size() == 2 && args[1] != "FILES") {
- sg->SetGroupRegex(args[1].c_str());
- return true;
- }
- // Process arguments.
- bool doingFiles = false;
- for (unsigned int i = 1; i < args.size(); ++i) {
- if (args[i] == "REGULAR_EXPRESSION") {
- // Next argument must specify the regex.
- if (i + 1 < args.size()) {
- ++i;
- sg->SetGroupRegex(args[i].c_str());
- } else {
- this->SetError("REGULAR_EXPRESSION argument given without a regex.");
- return false;
- }
- doingFiles = false;
- } else if (args[i] == "FILES") {
- // Next arguments will specify files.
- doingFiles = true;
- } else if (doingFiles) {
- // Convert name to full path and add to the group's list.
- std::string src = args[i];
- if (!cmSystemTools::FileIsFullPath(src.c_str())) {
+ if (parsedArguments.find(kTreeOptionName) != parsedArguments.end()) {
+ if (!processTree(parsedArguments, errorMsg)) {
+ this->SetError(errorMsg);
+ return false;
+ }
+ } else {
+ if (parsedArguments.find(kSourceGroupOptionName) ==
+ parsedArguments.end()) {
+ this->SetError("Missing source group name.");
+ return false;
+ }
+
+ cmSourceGroup* sg = this->Makefile->GetOrCreateSourceGroup(args[0]);
+
+ if (!sg) {
+ this->SetError("Could not create or find source group");
+ return false;
+ }
+
+ // handle regex
+ if (parsedArguments.find(kRegexOptionName) != parsedArguments.end()) {
+ const std::string& sgRegex = parsedArguments[kRegexOptionName].front();
+ sg->SetGroupRegex(sgRegex.c_str());
+ }
+
+ // handle files
+ const std::vector<std::string>& filesArguments =
+ parsedArguments[kFilesOptionName];
+ for (auto const& filesArg : filesArguments) {
+ std::string src = filesArg;
+ if (!cmSystemTools::FileIsFullPath(src)) {
src = this->Makefile->GetCurrentSourceDirectory();
src += "/";
- src += args[i];
+ src += filesArg;
}
src = cmSystemTools::CollapseFullPath(src);
sg->AddGroupFile(src);
- } else {
- std::ostringstream err;
- err << "Unknown argument \"" << args[i] << "\". "
- << "Perhaps the FILES keyword is missing.\n";
- this->SetError(err.str());
- return false;
}
}
return true;
}
-bool cmSourceGroupCommand::checkTreeArgumentsPreconditions(
- const std::vector<std::string>& args, std::string& errorMsg) const
+bool cmSourceGroupCommand::checkArgumentsPreconditions(
+ const ParsedArguments& parsedArguments, std::string& errorMsg) const
{
- if (args.size() == 1) {
- errorMsg = "TREE argument given without a root.";
- return false;
- }
-
- if (args.size() < 3) {
- errorMsg = "Missing FILES arguments.";
- return false;
- }
-
- if (args[FilesWithoutPrefixKeywordIndex] != "FILES" &&
- args[PrefixKeywordIndex] != "PREFIX") {
- errorMsg = "Unknown argument \"" + args[2] +
- "\". Perhaps the FILES keyword is missing.\n";
- return false;
- }
-
- if (args[PrefixKeywordIndex] == "PREFIX" &&
- (args.size() < 5 || args[FilesWithPrefixKeywordIndex] != "FILES")) {
- errorMsg = "Missing FILES arguments.";
+ if (!checkSingleParameterArgumentPreconditions(kPrefixOptionName,
+ parsedArguments, errorMsg) ||
+ !checkSingleParameterArgumentPreconditions(kTreeOptionName,
+ parsedArguments, errorMsg) ||
+ !checkSingleParameterArgumentPreconditions(kRegexOptionName,
+ parsedArguments, errorMsg)) {
return false;
}
return true;
}
-bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
+bool cmSourceGroupCommand::processTree(ParsedArguments& parsedArguments,
std::string& errorMsg)
{
- if (!checkTreeArgumentsPreconditions(args, errorMsg)) {
- return false;
- }
-
- const std::string root = cmSystemTools::CollapseFullPath(args[RootIndex]);
- std::string prefix;
- size_t filesBegin = FilesWithoutPrefixKeywordIndex + 1;
- if (args[PrefixKeywordIndex] == "PREFIX") {
- prefix = args[PrefixKeywordIndex + 1];
- filesBegin = FilesWithPrefixKeywordIndex + 1;
- }
+ const std::string root =
+ cmSystemTools::CollapseFullPath(parsedArguments[kTreeOptionName].front());
+ std::string prefix = parsedArguments[kPrefixOptionName].empty()
+ ? ""
+ : parsedArguments[kPrefixOptionName].front();
const std::vector<std::string> filesVector =
- prepareFilesPathsForTree(args.begin() + filesBegin, args.end(),
+ prepareFilesPathsForTree(parsedArguments[kFilesOptionName],
this->Makefile->GetCurrentSourceDirectory());
if (!rootIsPrefix(root, filesVector, errorMsg)) {
@@ -253,3 +289,25 @@ bool cmSourceGroupCommand::processTree(const std::vector<std::string>& args,
return true;
}
+
+bool cmSourceGroupCommand::checkSingleParameterArgumentPreconditions(
+ const std::string& argument, const ParsedArguments& parsedArguments,
+ std::string& errorMsg) const
+{
+ ParsedArguments::const_iterator foundArgument =
+ parsedArguments.find(argument);
+ if (foundArgument != parsedArguments.end()) {
+ const std::vector<std::string>& optionArguments = foundArgument->second;
+
+ if (optionArguments.empty()) {
+ errorMsg = argument + " argument given without an argument.";
+ return false;
+ }
+ if (optionArguments.size() > 1) {
+ errorMsg = "too many arguments passed to " + argument + ".";
+ return false;
+ }
+ }
+
+ return true;
+}
diff --git a/Source/cmSourceGroupCommand.h b/Source/cmSourceGroupCommand.h
index ed02ca59a..ec5ad329a 100644
--- a/Source/cmSourceGroupCommand.h
+++ b/Source/cmSourceGroupCommand.h
@@ -5,6 +5,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
+#include <map>
#include <string>
#include <vector>
@@ -34,10 +35,24 @@ public:
cmExecutionStatus& status) override;
private:
- bool processTree(const std::vector<std::string>& args,
- std::string& errorMsg);
- bool checkTreeArgumentsPreconditions(const std::vector<std::string>& args,
- std::string& errorMsg) const;
+ typedef std::map<std::string, std::vector<std::string>> ParsedArguments;
+ typedef std::vector<std::string> ExpectedOptions;
+
+ ExpectedOptions getExpectedOptions() const;
+
+ bool isExpectedOption(const std::string& argument,
+ const ExpectedOptions& expectedOptions);
+
+ void parseArguments(const std::vector<std::string>& args,
+ cmSourceGroupCommand::ParsedArguments& parsedArguments);
+
+ bool processTree(ParsedArguments& parsedArguments, std::string& errorMsg);
+
+ bool checkArgumentsPreconditions(const ParsedArguments& parsedArguments,
+ std::string& errorMsg) const;
+ bool checkSingleParameterArgumentPreconditions(
+ const std::string& argument, const ParsedArguments& parsedArguments,
+ std::string& errorMsg) const;
};
#endif
diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h
index c9f42e4ce..b212c7e2d 100644
--- a/Source/cmStandardLexer.h
+++ b/Source/cmStandardLexer.h
@@ -3,7 +3,7 @@
#ifndef cmStandardLexer_h
#define cmStandardLexer_h
-#include "cmConfigure.h" // IWYU pragma: keep
+#include "cmsys/Configure.h" // IWYU pragma: keep
/* Disable some warnings. */
#if defined(_MSC_VER)
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 5957b5bb2..bb891b579 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -93,7 +93,7 @@ cmStateEnums::CacheEntryType cmState::StringToCacheEntryType(const char* s)
bool cmState::IsCacheEntryType(std::string const& key)
{
for (int i = 0; cmCacheEntryTypes[i]; ++i) {
- if (strcmp(key.c_str(), cmCacheEntryTypes[i]) == 0) {
+ if (key == cmCacheEntryTypes[i]) {
return true;
}
}
@@ -107,9 +107,9 @@ bool cmState::LoadCache(const std::string& path, bool internal,
return this->CacheManager->LoadCache(path, internal, excludes, includes);
}
-bool cmState::SaveCache(const std::string& path)
+bool cmState::SaveCache(const std::string& path, cmMessenger* messenger)
{
- return this->CacheManager->SaveCache(path);
+ return this->CacheManager->SaveCache(path, messenger);
}
bool cmState::DeleteCache(const std::string& path)
@@ -514,9 +514,9 @@ void cmState::SetSourceDirectory(std::string const& sourceDirectory)
cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory);
}
-const char* cmState::GetSourceDirectory() const
+std::string const& cmState::GetSourceDirectory() const
{
- return this->SourceDirectory.c_str();
+ return this->SourceDirectory;
}
void cmState::SetBinaryDirectory(std::string const& binaryDirectory)
@@ -595,9 +595,9 @@ unsigned int cmState::GetCacheMinorVersion() const
return this->CacheManager->GetCacheMinorVersion();
}
-const char* cmState::GetBinaryDirectory() const
+std::string const& cmState::GetBinaryDirectory() const
{
- return this->BinaryDirectory.c_str();
+ return this->BinaryDirectory;
}
cmStateSnapshot cmState::CreateBaseSnapshot()
diff --git a/Source/cmState.h b/Source/cmState.h
index e03ad8981..6cbf82d5c 100644
--- a/Source/cmState.h
+++ b/Source/cmState.h
@@ -23,6 +23,7 @@ class cmCacheManager;
class cmCommand;
class cmPropertyDefinition;
class cmStateSnapshot;
+class cmMessenger;
class cmState
{
@@ -59,7 +60,7 @@ public:
std::set<std::string>& excludes,
std::set<std::string>& includes);
- bool SaveCache(const std::string& path);
+ bool SaveCache(const std::string& path, cmMessenger* messenger);
bool DeleteCache(const std::string& path);
@@ -137,9 +138,9 @@ public:
const char* GetGlobalProperty(const std::string& prop);
bool GetGlobalPropertyAsBool(const std::string& prop);
- const char* GetSourceDirectory() const;
+ std::string const& GetSourceDirectory() const;
void SetSourceDirectory(std::string const& sourceDirectory);
- const char* GetBinaryDirectory() const;
+ std::string const& GetBinaryDirectory() const;
void SetBinaryDirectory(std::string const& binaryDirectory);
void SetWindowsShell(bool windowsShell);
diff --git a/Source/cmStateSnapshot.cxx b/Source/cmStateSnapshot.cxx
index bdef3e529..479ecd228 100644
--- a/Source/cmStateSnapshot.cxx
+++ b/Source/cmStateSnapshot.cxx
@@ -386,6 +386,12 @@ void cmStateSnapshot::InitializeFromParent()
parent->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->BuildSystemDirectory->CompileOptionsBacktraces,
this->Position->CompileOptionsPosition);
+
+ const char* include_regex =
+ parent->BuildSystemDirectory->Properties.GetPropertyValue(
+ "INCLUDE_REGULAR_EXPRESSION");
+ this->Position->BuildSystemDirectory->Properties.SetProperty(
+ "INCLUDE_REGULAR_EXPRESSION", include_regex);
}
cmState* cmStateSnapshot::GetState() const
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 63c1452e6..eeb73c3ee 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -3,6 +3,7 @@
#include "cmSystemTools.h"
#include "cmAlgorithms.h"
+#include "cmDuration.h"
#include "cmProcessOutput.h"
#include "cm_sys_stat.h"
@@ -50,6 +51,10 @@
#include <windows.h>
// include wincrypt.h after windows.h
#include <wincrypt.h>
+
+#include <fcntl.h> /* _O_TEXT */
+
+#include "cm_uv.h"
#else
#include <sys/time.h>
#include <unistd.h>
@@ -545,12 +550,13 @@ std::vector<std::string> cmSystemTools::ParseArguments(const char* command)
bool win_path = false;
- if ((command[0] != '/' && command[1] == ':' && command[2] == '\\') ||
- (command[0] == '\"' && command[1] != '/' && command[2] == ':' &&
- command[3] == '\\') ||
- (command[0] == '\'' && command[1] != '/' && command[2] == ':' &&
- command[3] == '\\') ||
- (command[0] == '\\' && command[1] == '\\')) {
+ if (command[0] && command[1] &&
+ ((command[0] != '/' && command[1] == ':' && command[2] == '\\') ||
+ (command[0] == '\"' && command[1] != '/' && command[2] == ':' &&
+ command[3] == '\\') ||
+ (command[0] == '\'' && command[1] != '/' && command[2] == ':' &&
+ command[3] == '\\') ||
+ (command[0] == '\\' && command[1] == '\\'))) {
win_path = true;
}
// Split the command into an argv array.
@@ -697,7 +703,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
const char* dir, OutputOption outputflag,
- double timeout, Encoding encoding)
+ cmDuration timeout, Encoding encoding)
{
std::vector<const char*> argv;
argv.reserve(command.size() + 1);
@@ -725,7 +731,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command,
}
assert(!captureStdErr || captureStdErr != captureStdOut);
- cmsysProcess_SetTimeout(cp, timeout);
+ cmsysProcess_SetTimeout(cp, timeout.count());
cmsysProcess_Execute(cp);
std::vector<char> tempStdOut;
@@ -838,7 +844,7 @@ bool cmSystemTools::RunSingleCommand(const char* command,
std::string* captureStdOut,
std::string* captureStdErr, int* retVal,
const char* dir, OutputOption outputflag,
- double timeout)
+ cmDuration timeout)
{
if (s_DisableRunCommandOutput) {
outputflag = OUTPUT_NONE;
@@ -872,7 +878,7 @@ bool cmSystemTools::DoesFileExistWithExtensions(
hname = name;
hname += ".";
hname += headerExt;
- if (cmSystemTools::FileExists(hname.c_str())) {
+ if (cmSystemTools::FileExists(hname)) {
return true;
}
}
@@ -890,7 +896,7 @@ std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
std::string prevDir;
while (dir != prevDir) {
std::string path = dir + "/" + file;
- if (cmSystemTools::FileExists(path.c_str())) {
+ if (cmSystemTools::FileExists(path)) {
return path;
}
if (dir.size() < strlen(toplevel)) {
@@ -943,7 +949,55 @@ cmSystemTools::WindowsFileRetry cmSystemTools::GetWindowsFileRetry()
}
return retry;
}
+
+std::string cmSystemTools::GetRealPath(const std::string& path,
+ std::string* errorMessage)
+{
+ // uv_fs_realpath uses Windows Vista API so fallback to kwsys if not found
+ std::string resolved_path;
+ uv_fs_t req;
+ int err = uv_fs_realpath(NULL, &req, path.c_str(), NULL);
+ if (!err) {
+ resolved_path = std::string((char*)req.ptr);
+ cmSystemTools::ConvertToUnixSlashes(resolved_path);
+ // Normalize to upper-case drive letter as GetActualCaseForPath does.
+ if (resolved_path.size() > 1 && resolved_path[1] == ':') {
+ resolved_path[0] = toupper(resolved_path[0]);
+ }
+ } else if (err == UV_ENOSYS) {
+ resolved_path = cmsys::SystemTools::GetRealPath(path, errorMessage);
+ } else if (errorMessage) {
+ LPSTR message = NULL;
+ DWORD size = FormatMessageA(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&message, 0,
+ NULL);
+ *errorMessage = std::string(message, size);
+ LocalFree(message);
+
+ resolved_path = "";
+ } else {
+ resolved_path = path;
+ }
+ return resolved_path;
+}
+#endif
+
+void cmSystemTools::InitializeLibUV()
+{
+#if defined(_WIN32)
+ // Perform libuv one-time initialization now, and then un-do its
+ // global _fmode setting so that using libuv does not change the
+ // default file text/binary mode. See libuv issue 840.
+ uv_loop_close(uv_default_loop());
+#ifdef _MSC_VER
+ _set_fmode(_O_TEXT);
+#else
+ _fmode = _O_TEXT;
+#endif
#endif
+}
bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
{
@@ -1101,7 +1155,7 @@ void cmSystemTools::Glob(const std::string& directory,
for (i = 0; i < numf; i++) {
std::string fname = d.GetFile(i);
if (reg.find(fname)) {
- files.push_back(fname);
+ files.push_back(std::move(fname));
}
}
}
@@ -1273,6 +1327,9 @@ cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
if (ext == "java" || ext == ".java") {
return cmSystemTools::JAVA_FILE_FORMAT;
}
+ if (ext == "cu" || ext == ".cu") {
+ return cmSystemTools::CUDA_FILE_FORMAT;
+ }
if (ext == "H" || ext == ".H" || ext == "h" || ext == ".h" || ext == "h++" ||
ext == ".h++" || ext == "hm" || ext == ".hm" || ext == "hpp" ||
ext == ".hpp" || ext == "hxx" || ext == ".hxx" || ext == "in" ||
@@ -1315,7 +1372,7 @@ bool cmSystemTools::Split(const char* s, std::vector<std::string>& l)
return res;
}
-std::string cmSystemTools::ConvertToOutputPath(const char* path)
+std::string cmSystemTools::ConvertToOutputPath(std::string const& path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
if (s_ForceUnixPaths) {
@@ -1352,15 +1409,16 @@ std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
}
// compute the relative path from here to there
-std::string cmSystemTools::RelativePath(const char* local, const char* remote)
+std::string cmSystemTools::RelativePath(std::string const& local,
+ std::string const& remote)
{
if (!cmSystemTools::FileIsFullPath(local)) {
cmSystemTools::Error("RelativePath must be passed a full path to local: ",
- local);
+ local.c_str());
}
if (!cmSystemTools::FileIsFullPath(remote)) {
cmSystemTools::Error("RelativePath must be passed a full path to remote: ",
- remote);
+ remote.c_str());
}
return cmsys::SystemTools::RelativePath(local, remote);
}
@@ -1514,9 +1572,9 @@ bool cmSystemTools::CreateTar(const char* outFileName,
a.SetMTime(mtime);
a.SetVerbose(verbose);
for (auto path : files) {
- if (cmSystemTools::FileIsFullPath(path.c_str())) {
+ if (cmSystemTools::FileIsFullPath(path)) {
// Get the relative path to the file.
- path = cmSystemTools::RelativePath(cwd.c_str(), path.c_str());
+ path = cmSystemTools::RelativePath(cwd, path);
}
if (!a.Add(path)) {
break;
@@ -1773,7 +1831,7 @@ bool cmSystemTools::ListTar(const char* outFileName, bool verbose)
}
int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
- double timeout, std::vector<char>& out,
+ cmDuration timeout, std::vector<char>& out,
std::vector<char>& err)
{
line.clear();
@@ -1821,7 +1879,9 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
// No newlines found. Wait for more data from the process.
int length;
char* data;
- int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
+ double timeoutAsDbl = timeout.count();
+ int pipe =
+ cmsysProcess_WaitForData(process, &data, &length, &timeoutAsDbl);
if (pipe == cmsysProcess_Pipe_Timeout) {
// Timeout has been exceeded.
return pipe;
@@ -2052,8 +2112,12 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
(void)argv0; // ignore this on windows
wchar_t modulepath[_MAX_PATH];
::GetModuleFileNameW(NULL, modulepath, sizeof(modulepath));
- exe_dir =
- cmSystemTools::GetFilenamePath(cmsys::Encoding::ToNarrow(modulepath));
+ std::string path = cmsys::Encoding::ToNarrow(modulepath);
+ std::string realPath = cmSystemTools::GetRealPath(path, NULL);
+ if (realPath.empty()) {
+ realPath = path;
+ }
+ exe_dir = cmSystemTools::GetFilenamePath(realPath);
#elif defined(__APPLE__)
(void)argv0; // ignore this on OS X
#define CM_EXE_PATH_LOCAL_SIZE 16384
@@ -2115,19 +2179,19 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
cmSystemToolsCMakeGUICommand = exe_dir;
cmSystemToolsCMakeGUICommand += "/cmake-gui";
cmSystemToolsCMakeGUICommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand.c_str())) {
+ if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand)) {
cmSystemToolsCMakeGUICommand.clear();
}
cmSystemToolsCMakeCursesCommand = exe_dir;
cmSystemToolsCMakeCursesCommand += "/ccmake";
cmSystemToolsCMakeCursesCommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand.c_str())) {
+ if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand)) {
cmSystemToolsCMakeCursesCommand.clear();
}
cmSystemToolsCMClDepsCommand = exe_dir;
cmSystemToolsCMClDepsCommand += "/cmcldeps";
cmSystemToolsCMClDepsCommand += cmSystemTools::GetExecutableExtension();
- if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand.c_str())) {
+ if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand)) {
cmSystemToolsCMClDepsCommand.clear();
}
@@ -2142,7 +2206,7 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
}
if (cmSystemToolsCMakeRoot.empty() ||
!cmSystemTools::FileExists(
- (cmSystemToolsCMakeRoot + "/Modules/CMake.cmake").c_str())) {
+ (cmSystemToolsCMakeRoot + "/Modules/CMake.cmake"))) {
// Build tree has "<build>/bin[/<config>]/cmake" and
// "<build>/CMakeFiles/CMakeSourceDir.txt".
std::string dir = cmSystemTools::GetFilenamePath(exe_dir);
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index e7082e6b1..a53afded7 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -6,6 +6,7 @@
#include "cmConfigure.h" // IWYU pragma: keep
#include "cmCryptoHash.h"
+#include "cmDuration.h"
#include "cmProcessOutput.h"
#include "cmsys/Process.h"
#include "cmsys/SystemTools.hxx" // IWYU pragma: export
@@ -59,7 +60,7 @@ public:
* Set the function used by GUIs to display error messages
* Function gets passed: message as a const char*,
* title as a const char*, and a reference to bool that when
- * set to false, will disable furthur messages (cancel).
+ * set to false, will disable further messages (cancel).
*/
static void SetMessageCallback(MessageCallback f,
void* clientData = nullptr);
@@ -167,7 +168,7 @@ public:
* to be at the end of the string and it does not support ?
* []... The optional argument type specifies what kind of files you
* want to find. 0 means all files, -1 means directories, 1 means
- * files only. This method returns true if search was succesfull.
+ * files only. This method returns true if search was successful.
*/
static bool SimpleGlob(const std::string& glob,
std::vector<std::string>& files, int type = 0);
@@ -225,11 +226,11 @@ public:
int* retVal = nullptr,
const char* dir = nullptr,
OutputOption outputflag = OUTPUT_MERGE,
- double timeout = 0.0);
+ cmDuration timeout = cmDuration::zero());
/**
* In this version of RunSingleCommand, command[0] should be
* the command to run, and each argument to the command should
- * be in comand[1]...command[command.size()]
+ * be in command[1]...command[command.size()]
*/
static bool RunSingleCommand(std::vector<std::string> const& command,
std::string* captureStdOut = nullptr,
@@ -237,7 +238,7 @@ public:
int* retVal = nullptr,
const char* dir = nullptr,
OutputOption outputflag = OUTPUT_MERGE,
- double timeout = 0.0,
+ cmDuration timeout = cmDuration::zero(),
Encoding encoding = cmProcessOutput::Auto);
static std::string PrintSingleCommand(std::vector<std::string> const&);
@@ -285,6 +286,7 @@ public:
CXX_FILE_FORMAT,
FORTRAN_FILE_FORMAT,
JAVA_FILE_FORMAT,
+ CUDA_FILE_FORMAT,
HEADER_FILE_FORMAT,
RESOURCE_FILE_FORMAT,
DEFINITION_FILE_FORMAT,
@@ -342,7 +344,7 @@ public:
/** a general output handler for cmsysProcess */
static int WaitForLine(cmsysProcess* process, std::string& line,
- double timeout, std::vector<char>& out,
+ cmDuration timeout, std::vector<char>& out,
std::vector<char>& err);
/** Split a string on its newlines into multiple lines. Returns
@@ -352,7 +354,7 @@ public:
static bool GetForceUnixPaths() { return s_ForceUnixPaths; }
// ConvertToOutputPath use s_ForceUnixPaths
- static std::string ConvertToOutputPath(const char* path);
+ static std::string ConvertToOutputPath(std::string const& path);
static void ConvertToOutputSlashes(std::string& path);
// ConvertToRunCommandPath does not use s_ForceUnixPaths and should
@@ -368,7 +370,8 @@ public:
/a/b/c/d to /a/b/c1/d1 -> ../../c1/d1
from /usr/src to /usr/src/test/blah/foo.cpp -> test/blah/foo.cpp
*/
- static std::string RelativePath(const char* local, const char* remote);
+ static std::string RelativePath(std::string const& local,
+ std::string const& remote);
/** Joins two paths while collapsing x/../ parts
* For example CollapseCombinedPath("a/b/c", "../../d") results in "a/d"
@@ -497,7 +500,15 @@ public:
unsigned int Delay;
};
static WindowsFileRetry GetWindowsFileRetry();
+
+ /** Get the real path for a given path, removing all symlinks. */
+ static std::string GetRealPath(const std::string& path,
+ std::string* errorMessage = 0);
#endif
+
+ /** Perform one-time initialization of libuv. */
+ static void InitializeLibUV();
+
private:
static bool s_ForceUnixPaths;
static bool s_RunCommandHideConsole;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index c6cd5026f..cd11c4b14 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -23,6 +23,7 @@
#include "cmProperty.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
+#include "cmSourceFileLocationKind.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
@@ -176,6 +177,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
Visibility vis, cmMakefile* mf)
{
assert(mf);
+ this->IsGeneratorProvided = false;
this->Name = name;
this->TargetTypeValue = type;
this->Makefile = mf;
@@ -238,12 +240,14 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr);
this->SetPropertyDefault("Fortran_FORMAT", nullptr);
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", nullptr);
+ this->SetPropertyDefault("Fortran_COMPILER_LAUNCHER", nullptr);
this->SetPropertyDefault("GNUtoMS", nullptr);
this->SetPropertyDefault("OSX_ARCHITECTURES", nullptr);
this->SetPropertyDefault("IOS_INSTALL_COMBINED", nullptr);
this->SetPropertyDefault("AUTOMOC", nullptr);
this->SetPropertyDefault("AUTOUIC", nullptr);
this->SetPropertyDefault("AUTORCC", nullptr);
+ this->SetPropertyDefault("AUTOGEN_PARALLEL", nullptr);
this->SetPropertyDefault("AUTOMOC_COMPILER_PREDEFINES", nullptr);
this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", nullptr);
this->SetPropertyDefault("AUTOMOC_MACRO_NAMES", nullptr);
@@ -279,6 +283,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);
}
@@ -495,7 +500,7 @@ void cmTarget::AddSources(std::vector<std::string> const& srcs)
}
if (!srcFiles.empty()) {
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
- this->Internal->SourceEntries.push_back(srcFiles);
+ this->Internal->SourceEntries.push_back(std::move(srcFiles));
this->Internal->SourceBacktraces.push_back(lfbt);
}
}
@@ -603,7 +608,8 @@ public:
cmSourceFile* cmTarget::AddSource(const std::string& src)
{
- cmSourceFileLocation sfl(this->Makefile, src);
+ cmSourceFileLocation sfl(this->Makefile, src,
+ cmSourceFileLocationKind::Known);
if (std::find_if(this->Internal->SourceEntries.begin(),
this->Internal->SourceEntries.end(),
TargetPropertyEntryFinder(sfl)) ==
@@ -615,7 +621,8 @@ cmSourceFile* cmTarget::AddSource(const std::string& src)
if (cmGeneratorExpression::Find(src) != std::string::npos) {
return nullptr;
}
- return this->Makefile->GetOrCreateSource(src);
+ return this->Makefile->GetOrCreateSource(src, false,
+ cmSourceFileLocationKind::Known);
}
void cmTarget::AddLinkDirectory(const std::string& d)
@@ -740,10 +747,12 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib,
return;
}
- cmTarget::LibraryID tmp;
- tmp.first = lib;
- tmp.second = llt;
- this->OriginalLinkLibraries.push_back(tmp);
+ {
+ cmTarget::LibraryID tmp;
+ tmp.first = lib;
+ tmp.second = llt;
+ this->OriginalLinkLibraries.emplace_back(lib, llt);
+ }
// Add the explicit dependency information for this target. This is
// simply a set of libraries separated by ";". There should always
@@ -852,40 +861,61 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->Makefile->GetBacktrace())) {
return;
}
- if (prop == "MANUALLY_ADDED_DEPENDENCIES") {
+#define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
+ MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
+ MAKE_STATIC_PROP(COMPILE_FEATURES);
+ MAKE_STATIC_PROP(COMPILE_OPTIONS);
+ MAKE_STATIC_PROP(CUDA_PTX_COMPILATION);
+ MAKE_STATIC_PROP(EXPORT_NAME);
+ MAKE_STATIC_PROP(IMPORTED_GLOBAL);
+ MAKE_STATIC_PROP(INCLUDE_DIRECTORIES);
+ MAKE_STATIC_PROP(LINK_LIBRARIES);
+ MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
+ MAKE_STATIC_PROP(NAME);
+ MAKE_STATIC_PROP(SOURCES);
+ MAKE_STATIC_PROP(TYPE);
+#undef MAKE_STATIC_PROP
+ if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
std::ostringstream e;
e << "MANUALLY_ADDED_DEPENDENCIES property is read-only\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (prop == "NAME") {
+ if (prop == propNAME) {
std::ostringstream e;
e << "NAME property is read-only\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (prop == "TYPE") {
+ if (prop == propTYPE) {
std::ostringstream e;
e << "TYPE property is read-only\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (prop == "EXPORT_NAME" && this->IsImported()) {
+ if (prop == propEXPORT_NAME && this->IsImported()) {
std::ostringstream e;
e << "EXPORT_NAME property can't be set on imported targets (\""
<< this->Name << "\")\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
- if (prop == "SOURCES" && this->IsImported()) {
+ if (prop == propSOURCES && this->IsImported()) {
std::ostringstream e;
e << "SOURCES property can't be set on imported targets (\"" << this->Name
<< "\")\n";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
+ if (prop == propIMPORTED_GLOBAL && !this->IsImported()) {
+ std::ostringstream e;
+ e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
- if (prop == "INCLUDE_DIRECTORIES") {
+ if (prop == propINCLUDE_DIRECTORIES) {
this->Internal->IncludeDirectoriesEntries.clear();
this->Internal->IncludeDirectoriesBacktraces.clear();
if (value) {
@@ -893,7 +923,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->IncludeDirectoriesBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_OPTIONS") {
+ } else if (prop == propCOMPILE_OPTIONS) {
this->Internal->CompileOptionsEntries.clear();
this->Internal->CompileOptionsBacktraces.clear();
if (value) {
@@ -901,7 +931,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileOptionsBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_FEATURES") {
+ } else if (prop == propCOMPILE_FEATURES) {
this->Internal->CompileFeaturesEntries.clear();
this->Internal->CompileFeaturesBacktraces.clear();
if (value) {
@@ -909,7 +939,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileFeaturesBacktraces.push_back(lfbt);
}
- } else if (prop == "COMPILE_DEFINITIONS") {
+ } else if (prop == propCOMPILE_DEFINITIONS) {
this->Internal->CompileDefinitionsEntries.clear();
this->Internal->CompileDefinitionsBacktraces.clear();
if (value) {
@@ -917,7 +947,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
this->Internal->CompileDefinitionsBacktraces.push_back(lfbt);
}
- } else if (prop == "LINK_LIBRARIES") {
+ } else if (prop == propLINK_LIBRARIES) {
this->Internal->LinkImplementationPropertyEntries.clear();
this->Internal->LinkImplementationPropertyBacktraces.clear();
if (value) {
@@ -925,7 +955,7 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->Internal->LinkImplementationPropertyEntries.push_back(value);
this->Internal->LinkImplementationPropertyBacktraces.push_back(lfbt);
}
- } else if (prop == "SOURCES") {
+ } else if (prop == propSOURCES) {
this->Internal->SourceEntries.clear();
this->Internal->SourceBacktraces.clear();
if (value) {
@@ -933,10 +963,23 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
this->Internal->SourceEntries.push_back(value);
this->Internal->SourceBacktraces.push_back(lfbt);
}
+ } else if (prop == propIMPORTED_GLOBAL) {
+ if (!cmSystemTools::IsOn(value)) {
+ std::ostringstream e;
+ e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
+ /* no need to change anything if value does not change */
+ if (!this->ImportedGloballyVisible) {
+ this->ImportedGloballyVisible = true;
+ this->GetGlobalGenerator()->IndexTarget(this);
+ }
} else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") &&
!this->CheckImportedLibName(prop, value ? value : "")) {
/* error was reported by check method */
- } else if (prop == "CUDA_PTX_COMPILATION" &&
+ } else if (prop == propCUDA_PTX_COMPILATION &&
this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "CUDA_PTX_COMPILATION property can only be applied to OBJECT "
@@ -977,6 +1020,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
+ if (prop == "IMPORTED_GLOBAL") {
+ std::ostringstream e;
+ e << "IMPORTED_GLOBAL property can't be appended, only set on imported "
+ "targets (\""
+ << this->Name << "\")\n";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
+ return;
+ }
if (prop == "INCLUDE_DIRECTORIES") {
if (value && *value) {
this->Internal->IncludeDirectoriesEntries.push_back(value);
@@ -1143,6 +1194,21 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
context->IssueMessage(cmake::FATAL_ERROR, e.str());
}
+static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target,
+ cmMakefile* context)
+{
+ std::vector<cmTarget*> targets = context->GetOwnedImportedTargets();
+ std::vector<cmTarget*>::const_iterator it =
+ std::find(targets.begin(), targets.end(), target);
+ if (it == targets.end()) {
+ std::ostringstream e;
+ e << "Attempt to promote imported target \"" << target->GetName()
+ << "\" to global scope (by setting IMPORTED_GLOBAL) "
+ "which is not built in this directory.";
+ context->IssueMessage(cmake::FATAL_ERROR, e.str());
+ }
+}
+
void cmTarget::CheckProperty(const std::string& prop,
cmMakefile* context) const
{
@@ -1157,11 +1223,16 @@ void cmTarget::CheckProperty(const std::string& prop,
cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
}
}
- if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) {
+ if (prop == "INTERFACE_LINK_LIBRARIES") {
if (const char* value = this->GetProperty(prop)) {
cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
}
}
+ if (prop == "IMPORTED_GLOBAL") {
+ if (this->IsImported()) {
+ cmTargetCheckIMPORTED_GLOBAL(this, context);
+ }
+ }
}
const char* cmTarget::GetComputedProperty(
@@ -1182,6 +1253,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
MAKE_STATIC_PROP(COMPILE_OPTIONS);
MAKE_STATIC_PROP(COMPILE_DEFINITIONS);
MAKE_STATIC_PROP(IMPORTED);
+ MAKE_STATIC_PROP(IMPORTED_GLOBAL);
MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES);
MAKE_STATIC_PROP(NAME);
MAKE_STATIC_PROP(BINARY_DIR);
@@ -1196,6 +1268,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const
specialProps.insert(propCOMPILE_OPTIONS);
specialProps.insert(propCOMPILE_DEFINITIONS);
specialProps.insert(propIMPORTED);
+ specialProps.insert(propIMPORTED_GLOBAL);
specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES);
specialProps.insert(propNAME);
specialProps.insert(propBINARY_DIR);
@@ -1264,6 +1337,9 @@ const char* cmTarget::GetProperty(const std::string& prop) const
if (prop == propIMPORTED) {
return this->IsImported() ? "TRUE" : "FALSE";
}
+ if (prop == propIMPORTED_GLOBAL) {
+ return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE";
+ }
if (prop == propNAME) {
return this->GetName().c_str();
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 940e26c69..56f3e3a04 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -180,6 +180,12 @@ public:
bool GetHaveInstallRule() const { return this->HaveInstallRule; }
void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; }
+ /**
+ * Get/Set whether this target was auto-created by a generator.
+ */
+ bool GetIsGeneratorProvided() const { return this->IsGeneratorProvided; }
+ void SetIsGeneratorProvided(bool igp) { this->IsGeneratorProvided = igp; }
+
/** Add a utility on which this project depends. A utility is an executable
* name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE
* commands. It is not a full path nor does it have an extension.
@@ -284,6 +290,7 @@ private:
std::string const& value) const;
private:
+ bool IsGeneratorProvided;
cmPropertyMap Properties;
std::set<std::string> SystemIncludeDirectories;
std::set<std::string> LinkDirectoriesEmmitted;
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index d159d4178..4e716dc1f 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -17,15 +17,6 @@ bool cmTargetCompileDefinitionsCommand::InitialPass(
return this->HandleArguments(args, "COMPILE_DEFINITIONS");
}
-void cmTargetCompileDefinitionsCommand::HandleImportedTarget(
- const std::string& tgt)
-{
- std::ostringstream e;
- e << "Cannot specify compile definitions for imported target \"" << tgt
- << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
void cmTargetCompileDefinitionsCommand::HandleMissingTarget(
const std::string& name)
{
@@ -42,7 +33,7 @@ std::string cmTargetCompileDefinitionsCommand::Join(
std::string defs;
std::string sep;
for (std::string const& it : content) {
- if (cmHasLiteralPrefix(it.c_str(), "-D")) {
+ if (cmHasLiteralPrefix(it, "-D")) {
defs += sep + it.substr(2);
} else {
defs += sep + it;
@@ -56,5 +47,5 @@ bool cmTargetCompileDefinitionsCommand::HandleDirectContent(
cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
- return true;
+ return true; // Successfully handled.
}
diff --git a/Source/cmTargetCompileDefinitionsCommand.h b/Source/cmTargetCompileDefinitionsCommand.h
index f91045225..d41483a1d 100644
--- a/Source/cmTargetCompileDefinitionsCommand.h
+++ b/Source/cmTargetCompileDefinitionsCommand.h
@@ -30,7 +30,6 @@ public:
cmExecutionStatus& status) override;
private:
- void HandleImportedTarget(const std::string& tgt) override;
void HandleMissingTarget(const std::string& name) override;
bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 722bbe56c..f58e40414 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -17,15 +17,6 @@ bool cmTargetCompileFeaturesCommand::InitialPass(
return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
}
-void cmTargetCompileFeaturesCommand::HandleImportedTarget(
- const std::string& tgt)
-{
- std::ostringstream e;
- e << "Cannot specify compile features for imported target \"" << tgt
- << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
void cmTargetCompileFeaturesCommand::HandleMissingTarget(
const std::string& name)
{
@@ -49,8 +40,8 @@ bool cmTargetCompileFeaturesCommand::HandleDirectContent(
std::string error;
if (!this->Makefile->AddRequiredTargetFeature(tgt, it, &error)) {
this->SetError(error);
- return false;
+ return false; // Not (successfully) handled.
}
}
- return true;
+ return true; // Successfully handled.
}
diff --git a/Source/cmTargetCompileFeaturesCommand.h b/Source/cmTargetCompileFeaturesCommand.h
index 444d26069..45240a5a1 100644
--- a/Source/cmTargetCompileFeaturesCommand.h
+++ b/Source/cmTargetCompileFeaturesCommand.h
@@ -22,7 +22,6 @@ class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
cmExecutionStatus& status) override;
private:
- void HandleImportedTarget(const std::string& tgt) override;
void HandleMissingTarget(const std::string& name) override;
bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 1b4056d76..4df3630bb 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -18,21 +18,12 @@ bool cmTargetCompileOptionsCommand::InitialPass(
return this->HandleArguments(args, "COMPILE_OPTIONS", PROCESS_BEFORE);
}
-void cmTargetCompileOptionsCommand::HandleImportedTarget(
- const std::string& tgt)
-{
- std::ostringstream e;
- e << "Cannot specify compile options for imported target \"" << tgt << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
void cmTargetCompileOptionsCommand::HandleMissingTarget(
const std::string& name)
{
std::ostringstream e;
e << "Cannot specify compile options for target \"" << name
- << "\" "
- "which is not built by this project.";
+ << "\" which is not built by this project.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
@@ -47,5 +38,5 @@ bool cmTargetCompileOptionsCommand::HandleDirectContent(
{
cmListFileBacktrace lfbt = this->Makefile->GetBacktrace();
tgt->InsertCompileOption(this->Join(content), lfbt);
- return true;
+ return true; // Successfully handled.
}
diff --git a/Source/cmTargetCompileOptionsCommand.h b/Source/cmTargetCompileOptionsCommand.h
index 3fab238f2..6fb151a9d 100644
--- a/Source/cmTargetCompileOptionsCommand.h
+++ b/Source/cmTargetCompileOptionsCommand.h
@@ -30,7 +30,6 @@ public:
cmExecutionStatus& status) override;
private:
- void HandleImportedTarget(const std::string& tgt) override;
void HandleMissingTarget(const std::string& name) override;
bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h
index daa902ecf..b698db601 100644
--- a/Source/cmTargetDepend.h
+++ b/Source/cmTargetDepend.h
@@ -16,7 +16,7 @@ class cmTargetDepend
cmGeneratorTarget const* Target;
// The set order depends only on the Target, so we use
- // mutable members to acheive a map with set syntax.
+ // mutable members to achieve a map with set syntax.
mutable bool Link;
mutable bool Util;
diff --git a/Source/cmTargetIncludeDirectoriesCommand.cxx b/Source/cmTargetIncludeDirectoriesCommand.cxx
index 4646c7ee1..fc546cc3c 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.cxx
+++ b/Source/cmTargetIncludeDirectoriesCommand.cxx
@@ -21,22 +21,12 @@ bool cmTargetIncludeDirectoriesCommand::InitialPass(
ArgumentFlags(PROCESS_BEFORE | PROCESS_SYSTEM));
}
-void cmTargetIncludeDirectoriesCommand::HandleImportedTarget(
- const std::string& tgt)
-{
- std::ostringstream e;
- e << "Cannot specify include directories for imported target \"" << tgt
- << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
void cmTargetIncludeDirectoriesCommand::HandleMissingTarget(
const std::string& name)
{
std::ostringstream e;
e << "Cannot specify include directories for target \"" << name
- << "\" "
- "which is not built by this project.";
+ << "\" which is not built by this project.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
@@ -48,7 +38,7 @@ std::string cmTargetIncludeDirectoriesCommand::Join(
std::string prefix =
this->Makefile->GetCurrentSourceDirectory() + std::string("/");
for (std::string const& it : content) {
- if (cmSystemTools::FileIsFullPath(it.c_str()) ||
+ if (cmSystemTools::FileIsFullPath(it) ||
cmGeneratorExpression::Find(it) == 0) {
dirs += sep + it;
} else {
@@ -70,7 +60,7 @@ bool cmTargetIncludeDirectoriesCommand::HandleDirectContent(
this->Makefile->GetCurrentSourceDirectory() + std::string("/");
std::set<std::string> sdirs;
for (std::string const& it : content) {
- if (cmSystemTools::FileIsFullPath(it.c_str()) ||
+ if (cmSystemTools::FileIsFullPath(it) ||
cmGeneratorExpression::Find(it) == 0) {
sdirs.insert(it);
} else {
@@ -79,7 +69,7 @@ bool cmTargetIncludeDirectoriesCommand::HandleDirectContent(
}
tgt->AddSystemIncludeDirectories(sdirs);
}
- return true;
+ return true; // Successfully handled.
}
void cmTargetIncludeDirectoriesCommand::HandleInterfaceContent(
diff --git a/Source/cmTargetIncludeDirectoriesCommand.h b/Source/cmTargetIncludeDirectoriesCommand.h
index 27a2f437a..57bf8fcf3 100644
--- a/Source/cmTargetIncludeDirectoriesCommand.h
+++ b/Source/cmTargetIncludeDirectoriesCommand.h
@@ -30,7 +30,6 @@ public:
cmExecutionStatus& status) override;
private:
- void HandleImportedTarget(const std::string& tgt) override;
void HandleMissingTarget(const std::string& name) override;
bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index dda0464de..9e4575a69 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -25,21 +25,32 @@ const char* cmTargetLinkLibrariesCommand::LinkLibraryTypeNames[3] = {
bool cmTargetLinkLibrariesCommand::InitialPass(
std::vector<std::string> const& args, cmExecutionStatus&)
{
- // must have one argument
+ // Must have at least one argument.
if (args.empty()) {
this->SetError("called with incorrect number of arguments");
return false;
}
-
+ // Alias targets cannot be on the LHS of this command.
if (this->Makefile->IsAlias(args[0])) {
this->SetError("can not be used on an ALIAS target.");
return false;
}
+
// Lookup the target for which libraries are specified.
this->Target =
this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
args[0]);
if (!this->Target) {
+ const std::vector<cmTarget*>& importedTargets =
+ this->Makefile->GetOwnedImportedTargets();
+ for (cmTarget* importedTarget : importedTargets) {
+ if (importedTarget->GetName() == args[0]) {
+ this->Target = importedTarget;
+ break;
+ }
+ }
+ }
+ if (!this->Target) {
cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
std::ostringstream e;
e << "Cannot specify link libraries for target \"" << args[0] << "\" "
@@ -68,8 +79,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
break;
}
}
-
- // now actually print the message
+ // Now actually print the message.
switch (t) {
case cmake::AUTHOR_WARNING:
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str());
@@ -84,6 +94,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
return true;
}
+ // OBJECT libraries are not allowed on the LHS of the command.
if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
std::ostringstream e;
e << "Object library target \"" << args[0] << "\" "
@@ -93,6 +104,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
return true;
}
+ // Having a UTILITY library on the LHS is a bug.
if (this->Target->GetType() == cmStateEnums::UTILITY) {
std::ostringstream e;
const char* modal = nullptr;
@@ -119,7 +131,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
}
}
- // but we might not have any libs after variable expansion
+ // But we might not have any libs after variable expansion.
if (args.size() < 2) {
return true;
}
@@ -132,8 +144,8 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
// specification if the keyword is encountered as the first argument.
this->CurrentProcessingState = ProcessingLinkLibraries;
- // add libraries, note that there is an optional prefix
- // of debug and optimized that can be used
+ // Add libraries, note that there is an optional prefix
+ // of debug and optimized that can be used.
for (unsigned int i = 1; i < args.size(); ++i) {
if (args[i] == "LINK_INTERFACE_LIBRARIES") {
this->CurrentProcessingState = ProcessingPlainLinkInterface;
@@ -150,8 +162,9 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
this->CurrentProcessingState != ProcessingKeywordPublicInterface &&
this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
this->Makefile->IssueMessage(
- cmake::FATAL_ERROR, "The INTERFACE option must appear as the second "
- "argument, just after the target name.");
+ cmake::FATAL_ERROR,
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
+ "argument, just after the target name.");
return true;
}
this->CurrentProcessingState = ProcessingKeywordLinkInterface;
@@ -173,7 +186,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "The PUBLIC or PRIVATE option must appear as the second "
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
@@ -196,7 +209,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
this->Makefile->IssueMessage(
cmake::FATAL_ERROR,
- "The PUBLIC or PRIVATE option must appear as the second "
+ "The INTERFACE, PUBLIC or PRIVATE option must appear as the second "
"argument, just after the target name.");
return true;
}
@@ -228,8 +241,8 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
} else {
// Lookup old-style cache entry if type is unspecified. So if you
// do a target_link_libraries(foo optimized bar) it will stay optimized
- // and not use the lookup. As there maybe the case where someone has
- // specifed that a library is both debug and optimized. (this check is
+ // and not use the lookup. As there may be the case where someone has
+ // specified that a library is both debug and optimized. (this check is
// only there for backwards compatibility when mixing projects built
// with old versions of CMake and new)
llt = GENERAL_LibraryType;
@@ -299,6 +312,14 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
"target_link_libraries");
return false;
}
+ if (this->Target->IsImported() &&
+ this->CurrentProcessingState != ProcessingKeywordLinkInterface) {
+ this->Makefile->IssueMessage(
+ cmake::FATAL_ERROR,
+ "IMPORTED library can only be used with the INTERFACE keyword of "
+ "target_link_libraries");
+ return false;
+ }
cmTarget::TLLSignature sig =
(this->CurrentProcessingState == ProcessingPlainPrivateInterface ||
@@ -331,12 +352,11 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
// form must be the plain form.
const char* existingSig =
(sig == cmTarget::KeywordTLLSignature ? "plain" : "keyword");
- e << "The " << existingSig << " signature for target_link_libraries "
- "has already been used with the target \""
- << this->Target->GetName() << "\". All uses of "
- "target_link_libraries with a target "
- << modal << " be either "
- "all-keyword or all-plain.\n";
+ e << "The " << existingSig << " signature for target_link_libraries has "
+ "already been used with the target \""
+ << this->Target->GetName()
+ << "\". All uses of target_link_libraries with a target " << modal
+ << " be either all-keyword or all-plain.\n";
this->Target->GetTllSignatureTraces(e,
sig == cmTarget::KeywordTLLSignature
? cmTarget::PlainTLLSignature
@@ -348,104 +368,125 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
}
}
- // Handle normal case first.
+ // Handle normal case where the command was called with another keyword than
+ // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES"
+ // property of the target on the LHS shall be populated.)
if (this->CurrentProcessingState != ProcessingKeywordLinkInterface &&
this->CurrentProcessingState != ProcessingPlainLinkInterface) {
+ // Assure that the target on the LHS was created in the current directory.
cmTarget* t =
this->Makefile->FindLocalNonAliasTarget(this->Target->GetName());
if (!t) {
+ const std::vector<cmTarget*>& importedTargets =
+ this->Makefile->GetOwnedImportedTargets();
+ for (cmTarget* importedTarget : importedTargets) {
+ if (importedTarget->GetName() == this->Target->GetName()) {
+ t = importedTarget;
+ break;
+ }
+ }
+ }
+ if (!t) {
std::ostringstream e;
e << "Attempt to add link library \"" << lib << "\" to target \""
<< this->Target->GetName()
<< "\" which is not built in this directory.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- } else {
-
- cmTarget* tgt = this->Makefile->GetGlobalGenerator()->FindTarget(lib);
+ return false;
+ }
- if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
- (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
- (tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
- (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
- !tgt->IsExecutableWithExports()) {
- std::ostringstream e;
- e << "Target \"" << lib << "\" of type "
- << cmState::GetTargetTypeName(tgt->GetType())
- << " may not be linked into another target. "
- << "One may link only to STATIC or SHARED libraries, or "
- << "to executables with the ENABLE_EXPORTS property set.";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
- }
+ cmTarget* tgt = this->Makefile->GetGlobalGenerator()->FindTarget(lib);
- this->Target->AddLinkLibrary(*this->Makefile, lib, llt);
+ if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
+ (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
+ !tgt->IsExecutableWithExports()) {
+ std::ostringstream e;
+ e << "Target \"" << lib << "\" of type "
+ << cmState::GetTargetTypeName(tgt->GetType())
+ << " may not be linked into another target. One may link only to "
+ "INTERFACE, STATIC or SHARED libraries, or to executables with the "
+ "ENABLE_EXPORTS property set.";
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
- if (this->CurrentProcessingState == ProcessingLinkLibraries) {
- this->Target->AppendProperty(
- "INTERFACE_LINK_LIBRARIES",
- this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
- return true;
- }
- if (this->CurrentProcessingState != ProcessingKeywordPublicInterface &&
- this->CurrentProcessingState != ProcessingPlainPublicInterface) {
- if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
- std::string configLib =
- this->Target->GetDebugGeneratorExpressions(lib, llt);
- if (cmGeneratorExpression::IsValidTargetName(lib) ||
- cmGeneratorExpression::Find(lib) != std::string::npos) {
- configLib = "$<LINK_ONLY:" + configLib + ">";
- }
- this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
- configLib.c_str());
+ this->Target->AddLinkLibrary(*this->Makefile, lib, llt);
+ }
+
+ // Handle (additional) case where the command was called with PRIVATE /
+ // LINK_PRIVATE and stop its processing. (The "INTERFACE_LINK_LIBRARIES"
+ // property of the target on the LHS shall only be populated if it is a
+ // STATIC library.)
+ if (this->CurrentProcessingState == ProcessingKeywordPrivateInterface ||
+ this->CurrentProcessingState == ProcessingPlainPrivateInterface) {
+ if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) {
+ std::string configLib =
+ this->Target->GetDebugGeneratorExpressions(lib, llt);
+ if (cmGeneratorExpression::IsValidTargetName(lib) ||
+ cmGeneratorExpression::Find(lib) != std::string::npos) {
+ configLib = "$<LINK_ONLY:" + configLib + ">";
}
- // Not a 'public' or 'interface' library. Do not add to interface
- // property.
- return true;
+ this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES",
+ configLib.c_str());
}
+ return true;
}
+ // Handle general case where the command was called with another keyword than
+ // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES"
+ // property of the target on the LHS shall be populated.)
this->Target->AppendProperty(
"INTERFACE_LINK_LIBRARIES",
this->Target->GetDebugGeneratorExpressions(lib, llt).c_str());
+ // Stop processing if called without any keyword.
+ if (this->CurrentProcessingState == ProcessingLinkLibraries) {
+ return true;
+ }
+ // Stop processing if policy CMP0022 is set to NEW.
const cmPolicies::PolicyStatus policy22Status =
this->Target->GetPolicyStatusCMP0022();
-
if (policy22Status != cmPolicies::OLD &&
policy22Status != cmPolicies::WARN) {
return true;
}
-
+ // Stop processing if called with an INTERFACE library on the LHS.
if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
return true;
}
- // Get the list of configurations considered to be DEBUG.
- std::vector<std::string> debugConfigs =
- this->Makefile->GetCMakeInstance()->GetDebugConfigs();
- std::string prop;
-
- // Include this library in the link interface for the target.
- if (llt == DEBUG_LibraryType || llt == GENERAL_LibraryType) {
- // Put in the DEBUG configuration interfaces.
- for (std::string const& dc : debugConfigs) {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += dc;
- this->Target->AppendProperty(prop, lib.c_str());
+ // Handle (additional) backward-compatibility case where the command was
+ // called with PUBLIC / INTERFACE / LINK_PUBLIC / LINK_INTERFACE_LIBRARIES.
+ // (The policy CMP0022 is not set to NEW.)
+ {
+ // Get the list of configurations considered to be DEBUG.
+ std::vector<std::string> debugConfigs =
+ this->Makefile->GetCMakeInstance()->GetDebugConfigs();
+ std::string prop;
+
+ // Include this library in the link interface for the target.
+ if (llt == DEBUG_LibraryType || llt == GENERAL_LibraryType) {
+ // Put in the DEBUG configuration interfaces.
+ for (std::string const& dc : debugConfigs) {
+ prop = "LINK_INTERFACE_LIBRARIES_";
+ prop += dc;
+ this->Target->AppendProperty(prop, lib.c_str());
+ }
}
- }
- if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
- // Put in the non-DEBUG configuration interfaces.
- this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib.c_str());
-
- // Make sure the DEBUG configuration interfaces exist so that the
- // general one will not be used as a fall-back.
- for (std::string const& dc : debugConfigs) {
- prop = "LINK_INTERFACE_LIBRARIES_";
- prop += dc;
- if (!this->Target->GetProperty(prop)) {
- this->Target->SetProperty(prop, "");
+ if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
+ // Put in the non-DEBUG configuration interfaces.
+ this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib.c_str());
+
+ // Make sure the DEBUG configuration interfaces exist so that the
+ // general one will not be used as a fall-back.
+ for (std::string const& dc : debugConfigs) {
+ prop = "LINK_INTERFACE_LIBRARIES_";
+ prop += dc;
+ if (!this->Target->GetProperty(prop)) {
+ this->Target->SetProperty(prop, "");
+ }
}
}
}
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index f41af49d2..a2f3ecd4d 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -20,6 +20,9 @@ class cmTarget;
* cmTargetLinkLibrariesCommand is used to specify a list of libraries to link
* into executable(s) or shared objects. The names of the libraries
* should be those defined by the LIBRARY(library) command(s).
+ *
+ * Additionally, it allows to propagate usage-requirements (including link
+ * libraries) from one target into another.
*/
class cmTargetLinkLibrariesCommand : public cmCommand
{
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 45fe430c1..9a8fd96f1 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -17,11 +17,11 @@ bool cmTargetPropCommandBase::HandleArguments(
return false;
}
- // Lookup the target for which libraries are specified.
if (this->Makefile->IsAlias(args[0])) {
this->SetError("can not be used on an ALIAS target.");
return false;
}
+ // Lookup the target for which property-values are specified.
this->Target =
this->Makefile->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(
args[0]);
@@ -84,16 +84,13 @@ bool cmTargetPropCommandBase::ProcessContentArgs(
this->SetError("called with invalid arguments");
return false;
}
-
- if (this->Target->IsImported()) {
- this->HandleImportedTarget(args[0]);
- return false;
- }
-
if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
scope != "INTERFACE") {
- this->SetError("may only be set INTERFACE properties on INTERFACE "
- "targets");
+ this->SetError("may only set INTERFACE properties on INTERFACE targets");
+ return false;
+ }
+ if (this->Target->IsImported() && scope != "INTERFACE") {
+ this->SetError("may only set INTERFACE properties on IMPORTED targets");
return false;
}
diff --git a/Source/cmTargetPropCommandBase.h b/Source/cmTargetPropCommandBase.h
index 46a2f6b07..3c736fc0d 100644
--- a/Source/cmTargetPropCommandBase.h
+++ b/Source/cmTargetPropCommandBase.h
@@ -35,7 +35,6 @@ protected:
bool prepend, bool system);
private:
- virtual void HandleImportedTarget(const std::string& tgt) = 0;
virtual void HandleMissingTarget(const std::string& name) = 0;
virtual bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx
index 1d2520d4b..06ce0b1e6 100644
--- a/Source/cmTargetPropertyComputer.cxx
+++ b/Source/cmTargetPropertyComputer.cxx
@@ -3,6 +3,7 @@
#include "cmTargetPropertyComputer.h"
+#include <cctype>
#include <sstream>
#include <unordered_set>
@@ -49,6 +50,12 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
if (cmHasLiteralPrefix(prop, "INTERFACE_")) {
return true;
}
+ if (cmHasLiteralPrefix(prop, "_")) {
+ return true;
+ }
+ if (std::islower(prop[0])) {
+ return true;
+ }
static std::unordered_set<std::string> builtIns;
if (builtIns.empty()) {
builtIns.insert("COMPATIBLE_INTERFACE_BOOL");
@@ -57,6 +64,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty(
builtIns.insert("COMPATIBLE_INTERFACE_STRING");
builtIns.insert("EXPORT_NAME");
builtIns.insert("IMPORTED");
+ builtIns.insert("IMPORTED_GLOBAL");
builtIns.insert("NAME");
builtIns.insert("TYPE");
}
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 058659a52..3dd374879 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -17,13 +17,6 @@ bool cmTargetSourcesCommand::InitialPass(std::vector<std::string> const& args,
return this->HandleArguments(args, "SOURCES");
}
-void cmTargetSourcesCommand::HandleImportedTarget(const std::string& tgt)
-{
- std::ostringstream e;
- e << "Cannot specify sources for imported target \"" << tgt << "\".";
- this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
-}
-
void cmTargetSourcesCommand::HandleMissingTarget(const std::string& name)
{
std::ostringstream e;
@@ -43,5 +36,5 @@ bool cmTargetSourcesCommand::HandleDirectContent(
cmTarget* tgt, const std::vector<std::string>& content, bool, bool)
{
tgt->AppendProperty("SOURCES", this->Join(content).c_str());
- return true;
+ return true; // Successfully handled.
}
diff --git a/Source/cmTargetSourcesCommand.h b/Source/cmTargetSourcesCommand.h
index 0639e980e..ea8776abb 100644
--- a/Source/cmTargetSourcesCommand.h
+++ b/Source/cmTargetSourcesCommand.h
@@ -30,7 +30,6 @@ public:
cmExecutionStatus& status) override;
private:
- void HandleImportedTarget(const std::string& tgt) override;
void HandleMissingTarget(const std::string& name) override;
bool HandleDirectContent(cmTarget* tgt,
diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx
index 78ca6bca3..b5483593e 100644
--- a/Source/cmTestGenerator.cxx
+++ b/Source/cmTestGenerator.cxx
@@ -34,6 +34,16 @@ void cmTestGenerator::Compute(cmLocalGenerator* lg)
this->LG = lg;
}
+bool cmTestGenerator::TestsForConfig(const std::string& config)
+{
+ return this->GeneratesForConfig(config);
+}
+
+cmTest* cmTestGenerator::GetTest() const
+{
+ return this->Test;
+}
+
void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent)
{
// Create the tests.
diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h
index 1ca61c210..73d05a3bb 100644
--- a/Source/cmTestGenerator.h
+++ b/Source/cmTestGenerator.h
@@ -30,6 +30,11 @@ public:
void Compute(cmLocalGenerator* lg);
+ /** Test if this generator installs the test for a given configuration. */
+ bool TestsForConfig(const std::string& config);
+
+ cmTest* GetTest() const;
+
protected:
void GenerateScriptConfigs(std::ostream& os, Indent indent) override;
void GenerateScriptActions(std::ostream& os, Indent indent) override;
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 9fb79d945..f1e92839d 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -33,11 +33,13 @@ std::string cmTimestamp::FileModificationTime(const char* path,
const std::string& formatString,
bool utcFlag)
{
- if (!cmsys::SystemTools::FileExists(path)) {
+ std::string real_path = cmSystemTools::GetRealPath(path);
+
+ if (!cmsys::SystemTools::FileExists(real_path)) {
return std::string();
}
- time_t mtime = cmsys::SystemTools::ModifiedTime(path);
+ time_t mtime = cmsys::SystemTools::ModifiedTime(real_path);
return CreateTimestampFromTimeT(mtime, formatString, utcFlag);
}
@@ -151,7 +153,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
if (unixEpoch == -1) {
cmSystemTools::Error(
"Error generating UNIX epoch in "
- "STRING(TIMESTAMP ...). Please, file a bug report aginst CMake");
+ "STRING(TIMESTAMP ...). Please, file a bug report against CMake");
return std::string();
}
diff --git a/Source/cmTryCompileCommand.cxx b/Source/cmTryCompileCommand.cxx
index b6bfbfa69..3ff84ceb5 100644
--- a/Source/cmTryCompileCommand.cxx
+++ b/Source/cmTryCompileCommand.cxx
@@ -28,7 +28,7 @@ bool cmTryCompileCommand::InitialPass(std::vector<std::string> const& argv,
// if They specified clean then we clean up what we can
if (this->SrcFileSignature) {
if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
- this->CleanupFiles(this->BinaryDirectory.c_str());
+ this->CleanupFiles(this->BinaryDirectory);
}
}
return true;
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index dcaa4939e..939613802 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -4,8 +4,8 @@
#include "cmsys/FStream.hxx"
#include <stdio.h>
-#include <string.h>
+#include "cmDuration.h"
#include "cmMakefile.h"
#include "cmState.h"
#include "cmStateTypes.h"
@@ -153,7 +153,7 @@ bool cmTryRunCommand::InitialPass(std::vector<std::string> const& argv,
// if we created a directory etc, then cleanup after ourselves
if (!this->Makefile->GetCMakeInstance()->GetDebugTryCompile()) {
- this->CleanupFiles(this->BinaryDirectory.c_str());
+ this->CleanupFiles(this->BinaryDirectory);
}
return true;
}
@@ -186,18 +186,19 @@ void cmTryRunCommand::RunExecutable(const std::string& runArgs,
if (!runArgs.empty()) {
finalCommand += runArgs;
}
- int timeout = 0;
bool worked = cmSystemTools::RunSingleCommand(
finalCommand.c_str(), out, out, &retVal, nullptr,
- cmSystemTools::OUTPUT_NONE, timeout);
+ cmSystemTools::OUTPUT_NONE, cmDuration::zero());
// set the run var
- char retChar[1000];
+ char retChar[16];
+ const char* retStr;
if (worked) {
sprintf(retChar, "%i", retVal);
+ retStr = retChar;
} else {
- strcpy(retChar, "FAILED_TO_RUN");
+ retStr = "FAILED_TO_RUN";
}
- this->Makefile->AddCacheDefinition(this->RunResultVariable, retChar,
+ this->Makefile->AddCacheDefinition(this->RunResultVariable, retStr,
"Result of TRY_RUN",
cmStateEnums::INTERNAL);
}
diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx
new file mode 100644
index 000000000..eb70416c7
--- /dev/null
+++ b/Source/cmUVHandlePtr.cxx
@@ -0,0 +1,227 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#define cmUVHandlePtr_cxx
+#include "cmUVHandlePtr.h"
+
+#include <assert.h>
+#include <mutex>
+#include <stdlib.h>
+
+#include "cm_uv.h"
+
+namespace cm {
+
+static void close_delete(uv_handle_t* h)
+{
+ free(h);
+}
+
+template <typename T>
+static void default_delete(T* type_handle)
+{
+ auto handle = reinterpret_cast<uv_handle_t*>(type_handle);
+ if (handle) {
+ assert(!uv_is_closing(handle));
+ if (!uv_is_closing(handle)) {
+ uv_close(handle, &close_delete);
+ }
+ }
+}
+
+/**
+ * Encapsulates delete logic for a given handle type T
+ */
+template <typename T>
+struct uv_handle_deleter
+{
+ void operator()(T* type_handle) const { default_delete(type_handle); }
+};
+
+template <typename T>
+void uv_handle_ptr_base_<T>::allocate(void* data)
+{
+ reset();
+
+ /*
+ We use calloc since we know all these types are c structs
+ and we just want to 0 init them. New would do the same thing;
+ but casting from uv_handle_t to certain other types -- namely
+ uv_timer_t -- triggers a cast_align warning on certain systems.
+ */
+ handle.reset(static_cast<T*>(calloc(1, sizeof(T))), uv_handle_deleter<T>());
+ handle->data = data;
+}
+
+template <typename T>
+void uv_handle_ptr_base_<T>::reset()
+{
+ handle.reset();
+}
+
+template <typename T>
+uv_handle_ptr_base_<T>::operator uv_handle_t*()
+{
+ return reinterpret_cast<uv_handle_t*>(handle.get());
+}
+
+template <typename T>
+T* uv_handle_ptr_base_<T>::operator->() const noexcept
+{
+ return handle.get();
+}
+
+template <typename T>
+T* uv_handle_ptr_base_<T>::get() const
+{
+ return handle.get();
+}
+
+template <typename T>
+uv_handle_ptr_<T>::operator T*() const
+{
+ return this->handle.get();
+}
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+template <>
+struct uv_handle_deleter<uv_async_t>
+{
+ /***
+ * Wile uv_async_send is itself thread-safe, there are
+ * no strong guarantees that close hasn't already been
+ * called on the handle; and that it might be deleted
+ * as the send call goes through. This mutex guards
+ * against that.
+ *
+ * The shared_ptr here is to allow for copy construction
+ * which is mandated by the standard for Deleter on
+ * shared_ptrs.
+ */
+ std::shared_ptr<std::mutex> handleMutex;
+
+ uv_handle_deleter()
+ : handleMutex(std::make_shared<std::mutex>())
+ {
+ }
+
+ void operator()(uv_async_t* handle)
+ {
+ std::lock_guard<std::mutex> lock(*handleMutex);
+ default_delete(handle);
+ }
+};
+
+void uv_async_ptr::send()
+{
+ auto deleter = std::get_deleter<uv_handle_deleter<uv_async_t>>(this->handle);
+ assert(deleter);
+
+ std::lock_guard<std::mutex> lock(*deleter->handleMutex);
+ if (this->handle) {
+ uv_async_send(*this);
+ }
+}
+
+int uv_async_ptr::init(uv_loop_t& loop, uv_async_cb async_cb, void* data)
+{
+ allocate(data);
+ return uv_async_init(&loop, handle.get(), async_cb);
+}
+#endif
+
+template <>
+struct uv_handle_deleter<uv_signal_t>
+{
+ void operator()(uv_signal_t* handle) const
+ {
+ if (handle) {
+ uv_signal_stop(handle);
+ default_delete(handle);
+ }
+ }
+};
+
+int uv_signal_ptr::init(uv_loop_t& loop, void* data)
+{
+ allocate(data);
+ return uv_signal_init(&loop, handle.get());
+}
+
+int uv_signal_ptr::start(uv_signal_cb cb, int signum)
+{
+ assert(handle);
+ return uv_signal_start(*this, cb, signum);
+}
+
+void uv_signal_ptr::stop()
+{
+ if (handle) {
+ uv_signal_stop(*this);
+ }
+}
+
+int uv_pipe_ptr::init(uv_loop_t& loop, int ipc, void* data)
+{
+ allocate(data);
+ return uv_pipe_init(&loop, *this, ipc);
+}
+
+uv_pipe_ptr::operator uv_stream_t*() const
+{
+ return reinterpret_cast<uv_stream_t*>(handle.get());
+}
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+int uv_process_ptr::spawn(uv_loop_t& loop, uv_process_options_t const& options,
+ void* data)
+{
+ allocate(data);
+ return uv_spawn(&loop, *this, &options);
+}
+
+int uv_timer_ptr::init(uv_loop_t& loop, void* data)
+{
+ allocate(data);
+ return uv_timer_init(&loop, *this);
+}
+
+int uv_timer_ptr::start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat)
+{
+ assert(handle);
+ return uv_timer_start(*this, cb, timeout, repeat);
+}
+
+uv_tty_ptr::operator uv_stream_t*() const
+{
+ return reinterpret_cast<uv_stream_t*>(handle.get());
+}
+
+int uv_tty_ptr::init(uv_loop_t& loop, int fd, int readable, void* data)
+{
+ allocate(data);
+ return uv_tty_init(&loop, *this, fd, readable);
+}
+#endif
+
+template class uv_handle_ptr_base_<uv_handle_t>;
+
+#define UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(NAME) \
+ template class uv_handle_ptr_base_<uv_##NAME##_t>; \
+ template class uv_handle_ptr_<uv_##NAME##_t>;
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(signal)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(pipe)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(stream)
+
+#ifdef CMAKE_BUILD_WITH_CMAKE
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(async)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(process)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(timer)
+
+UV_HANDLE_PTR_INSTANTIATE_EXPLICIT(tty)
+#endif
+}
diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h
new file mode 100644
index 000000000..a6ce565c9
--- /dev/null
+++ b/Source/cmUVHandlePtr.h
@@ -0,0 +1,222 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <type_traits>
+
+#include "cm_uv.h"
+
+#define CM_PERFECT_FWD_CTOR(Class, FwdTo) \
+ template <typename... Args> \
+ Class(Args&&... args) \
+ : FwdTo(std::forward<Args>(args)...) \
+ { \
+ }
+
+namespace cm {
+
+/***
+* RAII class to simplify and insure the safe usage of uv_*_t types. This
+* includes making sure resources are properly freed and contains casting
+* operators which allow for passing into relevant uv_* functions.
+*
+*@tparam T actual uv_*_t type represented.
+*/
+template <typename T>
+class uv_handle_ptr_base_
+{
+protected:
+ template <typename _T>
+ friend class uv_handle_ptr_base_;
+
+ /**
+ * This must be a pointer type since the handle can outlive this class.
+ * When uv_close is eventually called on the handle, the memory the
+ * handle inhabits must be valid until the close callback is called
+ * which can be later on in the loop.
+ */
+ std::shared_ptr<T> handle;
+
+ /**
+ * Allocate memory for the type and optionally set it's 'data' pointer.
+ * Protected since this should only be called for an appropriate 'init'
+ * call.
+ *
+ * @param data data pointer to set
+ */
+ void allocate(void* data = nullptr);
+
+public:
+ CM_DISABLE_COPY(uv_handle_ptr_base_)
+ uv_handle_ptr_base_(uv_handle_ptr_base_&&) noexcept;
+ uv_handle_ptr_base_& operator=(uv_handle_ptr_base_&&) noexcept;
+
+ /**
+ * This move constructor allows us to move out of a more specialized
+ * uv type into a less specialized one. The only constraint is that
+ * the right hand side is castable to T.
+ *
+ * This allows you to return uv_handle_ptr or uv_stream_ptr from a function
+ * that initializes something like uv_pipe_ptr or uv_tcp_ptr and interact
+ * and clean up after it without caring about the exact type.
+ */
+ template <typename S, typename = typename std::enable_if<
+ std::is_rvalue_reference<S&&>::value>::type>
+ uv_handle_ptr_base_(S&& rhs)
+ {
+ // This will force a compiler error if rhs doesn't have a casting
+ // operator to get T*
+ this->handle = std::shared_ptr<T>(rhs.handle, rhs);
+ rhs.handle.reset();
+ }
+
+ // Dtor and ctor need to be inline defined like this for default ctors and
+ // dtors to work.
+ uv_handle_ptr_base_() {}
+ uv_handle_ptr_base_(std::nullptr_t) {}
+ ~uv_handle_ptr_base_() { reset(); }
+
+ /**
+ * Properly close the handle if needed and sets the inner handle to nullptr
+ */
+ void reset();
+
+ /**
+ * Allow less verbose calling of uv_handle_* functions
+ * @return reinterpreted handle
+ */
+ operator uv_handle_t*();
+
+ T* get() const;
+ T* operator->() const noexcept;
+};
+
+template <typename T>
+inline uv_handle_ptr_base_<T>::uv_handle_ptr_base_(
+ uv_handle_ptr_base_<T>&&) noexcept = default;
+template <typename T>
+inline uv_handle_ptr_base_<T>& uv_handle_ptr_base_<T>::operator=(
+ uv_handle_ptr_base_<T>&&) noexcept = default;
+
+/**
+ * While uv_handle_ptr_base_ only exposes uv_handle_t*, this exposes uv_T_t*
+ * too. It is broken out like this so we can reuse most of the code for the
+ * uv_handle_ptr class.
+ */
+template <typename T>
+class uv_handle_ptr_ : public uv_handle_ptr_base_<T>
+{
+ template <typename _T>
+ friend class uv_handle_ptr_;
+
+public:
+ CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<T>);
+
+ /***
+ * Allow less verbose calling of uv_<T> functions
+ * @return reinterpreted handle
+ */
+ operator T*() const;
+};
+
+/***
+ * This specialization is required to avoid duplicate 'operator uv_handle_t*()'
+ * declarations
+ */
+template <>
+class uv_handle_ptr_<uv_handle_t> : public uv_handle_ptr_base_<uv_handle_t>
+{
+public:
+ CM_PERFECT_FWD_CTOR(uv_handle_ptr_, uv_handle_ptr_base_<uv_handle_t>);
+};
+
+class uv_async_ptr : public uv_handle_ptr_<uv_async_t>
+{
+public:
+ CM_PERFECT_FWD_CTOR(uv_async_ptr, uv_handle_ptr_<uv_async_t>);
+
+ int init(uv_loop_t& loop, uv_async_cb async_cb, void* data = nullptr);
+
+ void send();
+};
+
+struct uv_signal_ptr : public uv_handle_ptr_<uv_signal_t>
+{
+ CM_PERFECT_FWD_CTOR(uv_signal_ptr, uv_handle_ptr_<uv_signal_t>);
+
+ int init(uv_loop_t& loop, void* data = nullptr);
+
+ int start(uv_signal_cb cb, int signum);
+
+ void stop();
+};
+
+struct uv_pipe_ptr : public uv_handle_ptr_<uv_pipe_t>
+{
+ CM_PERFECT_FWD_CTOR(uv_pipe_ptr, uv_handle_ptr_<uv_pipe_t>);
+
+ operator uv_stream_t*() const;
+
+ int init(uv_loop_t& loop, int ipc, void* data = nullptr);
+};
+
+struct uv_process_ptr : public uv_handle_ptr_<uv_process_t>
+{
+ CM_PERFECT_FWD_CTOR(uv_process_ptr, uv_handle_ptr_<uv_process_t>);
+
+ int spawn(uv_loop_t& loop, uv_process_options_t const& options,
+ void* data = nullptr);
+};
+
+struct uv_timer_ptr : public uv_handle_ptr_<uv_timer_t>
+{
+ CM_PERFECT_FWD_CTOR(uv_timer_ptr, uv_handle_ptr_<uv_timer_t>);
+
+ int init(uv_loop_t& loop, void* data = nullptr);
+
+ int start(uv_timer_cb cb, uint64_t timeout, uint64_t repeat);
+};
+
+struct uv_tty_ptr : public uv_handle_ptr_<uv_tty_t>
+{
+ CM_PERFECT_FWD_CTOR(uv_tty_ptr, uv_handle_ptr_<uv_tty_t>);
+
+ operator uv_stream_t*() const;
+
+ int init(uv_loop_t& loop, int fd, int readable, void* data = nullptr);
+};
+
+typedef uv_handle_ptr_<uv_stream_t> uv_stream_ptr;
+typedef uv_handle_ptr_<uv_handle_t> uv_handle_ptr;
+
+#ifndef cmUVHandlePtr_cxx
+
+extern template class uv_handle_ptr_base_<uv_handle_t>;
+
+#define UV_HANDLE_PTR_INSTANTIATE_EXTERN(NAME) \
+ extern template class uv_handle_ptr_base_<uv_##NAME##_t>; \
+ extern template class uv_handle_ptr_<uv_##NAME##_t>;
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(async)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(signal)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(pipe)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(process)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(stream)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(timer)
+
+UV_HANDLE_PTR_INSTANTIATE_EXTERN(tty)
+
+#undef UV_HANDLE_PTR_INSTANTIATE_EXTERN
+
+#endif
+}
diff --git a/Source/cmUVSignalHackRAII.h b/Source/cmUVSignalHackRAII.h
new file mode 100644
index 000000000..c019aea8e
--- /dev/null
+++ b/Source/cmUVSignalHackRAII.h
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#pragma once
+#include "cmConfigure.h" // IWYU pragma: keep
+
+#include "cm_uv.h"
+
+#if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) && \
+ UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19
+#define CMAKE_UV_SIGNAL_HACK
+#include "cmUVHandlePtr.h"
+/*
+ libuv does not use SA_RESTART on its signal handler, but C++ streams
+ depend on it for reliable i/o operations. This RAII helper convinces
+ libuv to install its handler, and then revises the handler to add the
+ SA_RESTART flag. We use a distinct uv loop that never runs to avoid
+ ever really getting a callback. libuv may fill the hack loop's signal
+ pipe and then stop writing, but that won't break any real loops.
+ */
+class cmUVSignalHackRAII
+{
+ uv_loop_t HackLoop;
+ cm::uv_signal_ptr HackSignal;
+ static void HackCB(uv_signal_t*, int) {}
+public:
+ cmUVSignalHackRAII()
+ {
+ uv_loop_init(&this->HackLoop);
+ this->HackSignal.init(this->HackLoop);
+ this->HackSignal.start(HackCB, SIGCHLD);
+ struct sigaction hack_sa;
+ sigaction(SIGCHLD, nullptr, &hack_sa);
+ if (!(hack_sa.sa_flags & SA_RESTART)) {
+ hack_sa.sa_flags |= SA_RESTART;
+ sigaction(SIGCHLD, &hack_sa, nullptr);
+ }
+ }
+ ~cmUVSignalHackRAII()
+ {
+ this->HackSignal.stop();
+ uv_loop_close(&this->HackLoop);
+ }
+};
+#endif
diff --git a/Source/cmUnsetCommand.cxx b/Source/cmUnsetCommand.cxx
index 18bbdd748..cfaa1fd27 100644
--- a/Source/cmUnsetCommand.cxx
+++ b/Source/cmUnsetCommand.cxx
@@ -2,8 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmUnsetCommand.h"
-#include <string.h>
-
#include "cmAlgorithms.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
@@ -19,19 +17,16 @@ bool cmUnsetCommand::InitialPass(std::vector<std::string> const& args,
return false;
}
- const char* variable = args[0].c_str();
+ auto const& variable = args[0];
// unset(ENV{VAR})
- if (cmHasLiteralPrefix(variable, "ENV{") && strlen(variable) > 5) {
+ if (cmHasLiteralPrefix(variable, "ENV{") && variable.size() > 5) {
// what is the variable name
- char* envVarName = new char[strlen(variable)];
- strncpy(envVarName, variable + 4, strlen(variable) - 5);
- envVarName[strlen(variable) - 5] = '\0';
+ auto const& envVarName = variable.substr(4, variable.size() - 5);
#ifdef CMAKE_BUILD_WITH_CMAKE
- cmSystemTools::UnsetEnv(envVarName);
+ cmSystemTools::UnsetEnv(envVarName.c_str());
#endif
- delete[] envVarName;
return true;
}
// unset(VAR)
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index c04a68327..ea012f6ca 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -13,8 +13,8 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
cmExecutionStatus&)
{
// expected two arguments:
- // arguement one: the full path to gl_mangle.h
- // arguement two : directory for output of edited headers
+ // argument one: the full path to gl_mangle.h
+ // argument two : directory for output of edited headers
if (args.size() != 2) {
this->SetError("called with incorrect number of arguments");
return false;
@@ -23,7 +23,7 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
std::string glh = inputDir;
glh += "/";
glh += "gl.h";
- if (!cmSystemTools::FileExists(glh.c_str())) {
+ if (!cmSystemTools::FileExists(glh)) {
std::string e = "Bad path to Mesa, could not find: ";
e += glh;
e += " ";
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index 0ce437c1a..114080090 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -66,14 +66,14 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
utilitySource = utilitySource + "/" + relativeSource;
// If the directory doesn't exist, the source has not been included.
- if (!cmSystemTools::FileExists(utilitySource.c_str())) {
+ if (!cmSystemTools::FileExists(utilitySource)) {
return true;
}
// Make sure all the files exist in the source directory.
while (arg != args.end()) {
std::string file = utilitySource + "/" + *arg++;
- if (!cmSystemTools::FileExists(file.c_str())) {
+ if (!cmSystemTools::FileExists(file)) {
return true;
}
}
diff --git a/Source/cmUtils.hxx b/Source/cmUtils.hxx
index c5c767c02..a7a3e81f6 100644
--- a/Source/cmUtils.hxx
+++ b/Source/cmUtils.hxx
@@ -7,7 +7,7 @@
// Use the make system's VERBOSE environment variable to enable
// verbose output. This can be skipped by also setting CMAKE_NO_VERBOSE
-// (which is set by the Eclipse and KDevelop generators).
+// (which is set by the Eclipse generator).
inline bool isCMakeVerbose()
{
return (cmSystemTools::HasEnv("VERBOSE") &&
diff --git a/Source/cmVS141CLFlagTable.h b/Source/cmVS141CLFlagTable.h
index c780d469a..7d3e35602 100644
--- a/Source/cmVS141CLFlagTable.h
+++ b/Source/cmVS141CLFlagTable.h
@@ -1,6 +1,10 @@
static cmVS7FlagTable cmVS141CLFlagTable[] = {
// Enum Properties
+ { "DiagnosticsFormat", "diagnostics:classic", "Classic", "Classic", 0 },
+ { "DiagnosticsFormat", "diagnostics:column", "Column", "Column", 0 },
+ { "DiagnosticsFormat", "diagnostics:caret", "Caret", "Caret", 0 },
+
{ "DebugInformationFormat", "", "None", "None", 0 },
{ "DebugInformationFormat", "Z7", "C7 compatible", "OldStyle", 0 },
{ "DebugInformationFormat", "Zi", "Program Database", "ProgramDatabase", 0 },
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index ea13649c2..c2f8debc8 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -80,6 +80,14 @@ cmVSSetupAPIHelper::~cmVSSetupAPIHelper()
CoUninitialize();
}
+bool cmVSSetupAPIHelper::SetVSInstance(std::string const& vsInstallLocation)
+{
+ this->SpecifiedVSInstallLocation = vsInstallLocation;
+ cmSystemTools::ConvertToUnixSlashes(this->SpecifiedVSInstallLocation);
+ chosenInstanceInfo = VSInstanceInfo();
+ return this->EnumerateAndChooseVSInstance();
+}
+
bool cmVSSetupAPIHelper::IsVS2017Installed()
{
return this->EnumerateAndChooseVSInstance();
@@ -265,13 +273,6 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
if (cmSystemTools::GetEnv("VS150COMNTOOLS", envVSCommonToolsDir)) {
cmSystemTools::ConvertToUnixSlashes(envVSCommonToolsDir);
}
- // FIXME: If the environment variable value changes between runs
- // of CMake within a given build tree the results are not defined.
- // Instead we should save a CMAKE_GENERATOR_INSTANCE value in the cache
- // (similar to CMAKE_GENERATOR_TOOLSET) to hold it persistently.
- // Unfortunately doing so will require refactoring elsewhere in
- // order to make sure the value is available in time to create
- // the generator.
std::vector<VSInstanceInfo> vecVSInstances;
SmartCOMPtr<IEnumSetupInstances> enumInstances = NULL;
@@ -296,16 +297,29 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
instance = instance2 = NULL;
if (isInstalled) {
- if (!envVSCommonToolsDir.empty()) {
+ if (!this->SpecifiedVSInstallLocation.empty()) {
+ // We are looking for a specific instance.
std::string currentVSLocation = instanceInfo.GetInstallLocation();
- currentVSLocation += "/Common7/Tools";
if (cmSystemTools::ComparePath(currentVSLocation,
- envVSCommonToolsDir)) {
+ this->SpecifiedVSInstallLocation)) {
chosenInstanceInfo = instanceInfo;
return true;
}
+ } else {
+ // We are not looking for a specific instance.
+ // If we've been given a hint then use it.
+ if (!envVSCommonToolsDir.empty()) {
+ std::string currentVSLocation = instanceInfo.GetInstallLocation();
+ currentVSLocation += "/Common7/Tools";
+ if (cmSystemTools::ComparePath(currentVSLocation,
+ envVSCommonToolsDir)) {
+ chosenInstanceInfo = instanceInfo;
+ return true;
+ }
+ }
+ // Otherwise, add this to the list of candidates.
+ vecVSInstances.push_back(instanceInfo);
}
- vecVSInstances.push_back(instanceInfo);
}
}
diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h
index 74a7ec04a..c07cfafc2 100644
--- a/Source/cmVSSetupHelper.h
+++ b/Source/cmVSSetupHelper.h
@@ -126,6 +126,8 @@ public:
cmVSSetupAPIHelper();
~cmVSSetupAPIHelper();
+ bool SetVSInstance(std::string const& vsInstallLocation);
+
bool IsVS2017Installed();
bool GetVSInstanceInfo(std::string& vsInstallLocation);
bool IsWin10SDKInstalled();
@@ -150,6 +152,8 @@ private:
HRESULT comInitialized;
// current best instance of VS selected
VSInstanceInfo chosenInstanceInfo;
+
+ std::string SpecifiedVSInstallLocation;
};
#endif
diff --git a/Source/cmVariableWatchCommand.cxx b/Source/cmVariableWatchCommand.cxx
index 9930086f4..e080df1ec 100644
--- a/Source/cmVariableWatchCommand.cxx
+++ b/Source/cmVariableWatchCommand.cxx
@@ -43,16 +43,14 @@ static void cmVariableWatchCommandVariableAccessed(const std::string& variable,
std::string stack = makefile->GetProperty("LISTFILE_STACK");
if (!data->Command.empty()) {
newLFF.Arguments.clear();
- newLFF.Arguments.push_back(
- cmListFileArgument(variable, cmListFileArgument::Quoted, 9999));
- newLFF.Arguments.push_back(
- cmListFileArgument(accessString, cmListFileArgument::Quoted, 9999));
- newLFF.Arguments.push_back(cmListFileArgument(
- newValue ? newValue : "", cmListFileArgument::Quoted, 9999));
- newLFF.Arguments.push_back(
- cmListFileArgument(currentListFile, cmListFileArgument::Quoted, 9999));
- newLFF.Arguments.push_back(
- cmListFileArgument(stack, cmListFileArgument::Quoted, 9999));
+ newLFF.Arguments.emplace_back(variable, cmListFileArgument::Quoted, 9999);
+ newLFF.Arguments.emplace_back(accessString, cmListFileArgument::Quoted,
+ 9999);
+ newLFF.Arguments.emplace_back(newValue ? newValue : "",
+ cmListFileArgument::Quoted, 9999);
+ newLFF.Arguments.emplace_back(currentListFile, cmListFileArgument::Quoted,
+ 9999);
+ newLFF.Arguments.emplace_back(stack, cmListFileArgument::Quoted, 9999);
newLFF.Name = data->Command;
newLFF.Line = 9999;
cmExecutionStatus status;
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index c61902ab6..ec31bd628 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -15,8 +15,11 @@
#include "cmVisualStudioGeneratorOptions.h"
#include "windows.h"
+#include <iterator>
#include <memory> // IWYU pragma: keep
+static void ConvertToWindowsSlash(std::string& s);
+
static std::string cmVS10EscapeXML(std::string arg)
{
cmSystemTools::ReplaceString(arg, "&", "&amp;");
@@ -37,8 +40,8 @@ static std::string cmVS10EscapeComment(std::string comment)
// does "echo $CDATA" with no escapes. We must encode the string.
// http://technet.microsoft.com/en-us/library/cc772462%28WS.10%29.aspx
std::string echoable;
- for (std::string::iterator c = comment.begin(); c != comment.end(); ++c) {
- switch (*c) {
+ for (char c : comment) {
+ switch (c) {
case '\r':
break;
case '\n':
@@ -51,8 +54,9 @@ static std::string cmVS10EscapeComment(std::string comment)
case '>': /* no break */
case '^':
echoable += '^'; /* no break */
+ CM_FALLTHROUGH;
default:
- echoable += *c;
+ echoable += c;
break;
}
}
@@ -65,11 +69,14 @@ static bool cmVS10IsTargetsFile(std::string const& path)
return cmSystemTools::Strucmp(ext.c_str(), ".targets") == 0;
}
-static std::string computeProjectFileExtension(cmGeneratorTarget const* t)
+static std::string computeProjectFileExtension(cmGeneratorTarget const* t,
+ const std::string& config)
{
std::string res;
res = ".vcxproj";
- if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t)) {
+ std::string lang = t->GetLinkerLanguage(config);
+ if (cmGlobalVisualStudioGenerator::TargetIsCSharpOnly(t) ||
+ lang == "CSharp") {
res = ".csproj";
}
return res;
@@ -109,22 +116,6 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator(
cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator()
{
- for (OptionsMap::iterator i = this->ClOptions.begin();
- i != this->ClOptions.end(); ++i) {
- delete i->second;
- }
- for (OptionsMap::iterator i = this->LinkOptions.begin();
- i != this->LinkOptions.end(); ++i) {
- delete i->second;
- }
- for (OptionsMap::iterator i = this->CudaOptions.begin();
- i != this->CudaOptions.end(); ++i) {
- delete i->second;
- }
- for (OptionsMap::iterator i = this->CudaLinkOptions.begin();
- i != this->CudaLinkOptions.end(); ++i) {
- delete i->second;
- }
if (!this->BuildFileStream) {
return;
}
@@ -198,8 +189,8 @@ void cmVisualStudio10TargetGenerator::Generate()
this->GeneratorTarget->GetProperty("EXTERNAL_MSPROJECT")) {
return;
}
- this->ProjectFileExtension =
- computeProjectFileExtension(this->GeneratorTarget);
+ this->ProjectFileExtension = computeProjectFileExtension(
+ this->GeneratorTarget, *this->Configurations.begin());
if (this->ProjectFileExtension == ".vcxproj") {
this->ProjectType = vcxproj;
this->Managed = false;
@@ -400,18 +391,17 @@ void cmVisualStudio10TargetGenerator::Generate()
}
std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys();
- for (std::vector<std::string>::const_iterator keyIt = keys.begin();
- keyIt != keys.end(); ++keyIt) {
+ for (std::string const& keyIt : keys) {
static const char* prefix = "VS_GLOBAL_";
- if (keyIt->find(prefix) != 0)
+ if (keyIt.find(prefix) != 0)
continue;
- std::string globalKey = keyIt->substr(strlen(prefix));
+ std::string globalKey = keyIt.substr(strlen(prefix));
// Skip invalid or separately-handled properties.
if (globalKey.empty() || globalKey == "PROJECT_TYPES" ||
globalKey == "ROOTNAMESPACE" || globalKey == "KEYWORD") {
continue;
}
- const char* value = this->GeneratorTarget->GetProperty(*keyIt);
+ const char* value = this->GeneratorTarget->GetProperty(keyIt);
if (!value)
continue;
this->WriteString("<", 2);
@@ -494,7 +484,7 @@ void cmVisualStudio10TargetGenerator::Generate()
std::string propsLocal;
propsLocal += this->DefaultArtifactDir;
propsLocal += "\\nasm.props";
- this->ConvertToWindowsSlash(propsLocal);
+ ConvertToWindowsSlash(propsLocal);
this->Makefile->ConfigureFile(propsTemplate.c_str(), propsLocal.c_str(),
false, true, true);
std::string import = std::string("<Import Project=\"") +
@@ -517,7 +507,7 @@ void cmVisualStudio10TargetGenerator::Generate()
props = p;
}
if (!props.empty()) {
- this->ConvertToWindowsSlash(props);
+ ConvertToWindowsSlash(props);
this->WriteString("", 2);
(*this->BuildFileStream)
<< "<Import Project=\"" << cmVS10EscapeXML(props) << "\""
@@ -573,22 +563,18 @@ void cmVisualStudio10TargetGenerator::Generate()
}
this->WriteString("</ImportGroup>\n", 1);
if (this->ProjectType == csproj) {
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
+ for (std::string const& i : this->Configurations) {
this->WriteString("<PropertyGroup Condition=\"'$(Configuration)' == '",
1);
- (*this->BuildFileStream) << *i << "'\">\n";
- this->WriteEvents(*i);
+ (*this->BuildFileStream) << i << "'\">\n";
+ this->WriteEvents(i);
this->WriteString("</PropertyGroup>\n", 1);
}
// make sure custom commands are executed before build (if necessary)
this->WriteString("<PropertyGroup>\n", 1);
this->WriteString("<BuildDependsOn>\n", 2);
- for (std::set<std::string>::const_iterator i =
- this->CSharpCustomCommandNames.begin();
- i != this->CSharpCustomCommandNames.end(); ++i) {
- this->WriteString(i->c_str(), 3);
+ for (std::string const& i : this->CSharpCustomCommandNames) {
+ this->WriteString(i.c_str(), 3);
(*this->BuildFileStream) << ";\n";
}
this->WriteString("$(BuildDependsOn)\n", 3);
@@ -610,42 +596,37 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferences()
cmSystemTools::ExpandListArgument(vsDotNetReferences, references);
}
cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
- for (cmPropertyMap::const_iterator i = props.begin(); i != props.end();
- ++i) {
- if (i->first.find("VS_DOTNET_REFERENCE_") == 0) {
- std::string name = i->first.substr(20);
+ for (auto const& i : props) {
+ if (i.first.find("VS_DOTNET_REFERENCE_") == 0) {
+ std::string name = i.first.substr(20);
if (!name.empty()) {
- std::string path = i->second.GetValue();
+ std::string path = i.second.GetValue();
if (!cmsys::SystemTools::FileIsFullPath(path)) {
path = std::string(this->GeneratorTarget->Target->GetMakefile()
->GetCurrentSourceDirectory()) +
"/" + path;
}
- this->ConvertToWindowsSlash(path);
+ ConvertToWindowsSlash(path);
hintReferences.push_back(HintReference(name, path));
}
}
}
if (!references.empty() || !hintReferences.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::iterator ri = references.begin();
- ri != references.end(); ++ri) {
+ for (std::string const& ri : references) {
// if the entry from VS_DOTNET_REFERENCES is an existing file, generate
// a new hint-reference and name it from the filename
- if (cmsys::SystemTools::FileExists(*ri, true)) {
- std::string name =
- cmsys::SystemTools::GetFilenameWithoutExtension(*ri);
- std::string path = *ri;
- this->ConvertToWindowsSlash(path);
+ if (cmsys::SystemTools::FileExists(ri, true)) {
+ std::string name = cmsys::SystemTools::GetFilenameWithoutExtension(ri);
+ std::string path = ri;
+ ConvertToWindowsSlash(path);
hintReferences.push_back(HintReference(name, path));
} else {
- this->WriteDotNetReference(*ri, "");
+ this->WriteDotNetReference(ri, "");
}
}
- for (std::vector<std::pair<std::string, std::string>>::const_iterator i =
- hintReferences.begin();
- i != hintReferences.end(); ++i) {
- this->WriteDotNetReference(i->first, i->second);
+ for (const auto& i : hintReferences) {
+ this->WriteDotNetReference(i.first, i.second);
}
this->WriteString("</ItemGroup>\n", 1);
}
@@ -689,22 +670,19 @@ void cmVisualStudio10TargetGenerator::WriteDotNetReferenceCustomTags(
typedef std::map<std::string, std::string> CustomTags;
CustomTags tags;
cmPropertyMap const& props = this->GeneratorTarget->Target->GetProperties();
- for (cmPropertyMap::const_iterator i = props.begin(); i != props.end();
- ++i) {
- if (i->first.find(refPropFullPrefix) == 0) {
- std::string refTag = i->first.substr(refPropFullPrefix.length());
- std::string refVal = i->second.GetValue();
+ for (const auto& i : props) {
+ if (i.first.find(refPropFullPrefix) == 0) {
+ std::string refTag = i.first.substr(refPropFullPrefix.length());
+ std::string refVal = i.second.GetValue();
if (!refTag.empty() && !refVal.empty()) {
tags[refTag] = refVal;
}
}
}
- for (CustomTags::const_iterator tag = tags.begin(); tag != tags.end();
- ++tag) {
+ for (auto const& tag : tags) {
this->WriteString("<", 3);
- (*this->BuildFileStream) << tag->first << ">"
- << cmVS10EscapeXML(tag->second) << "</"
- << tag->first << ">\n";
+ (*this->BuildFileStream) << tag.first << ">" << cmVS10EscapeXML(tag.second)
+ << "</" << tag.first << ">\n";
}
}
@@ -715,13 +693,11 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
if (!resxObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
- this->ConvertToWindowsSlash(srcDir);
- for (std::vector<cmSourceFile const*>::const_iterator oi =
- resxObjs.begin();
- oi != resxObjs.end(); ++oi) {
- std::string obj = (*oi)->GetFullPath();
+ ConvertToWindowsSlash(srcDir);
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
this->WriteString("<EmbeddedResource Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
+ ConvertToWindowsSlash(obj);
bool useRelativePath = false;
if (this->ProjectType == csproj && this->InSourceBuild) {
// If we do an in-source build and the resource file is in a
@@ -730,7 +706,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
// visual studio does not show the file in the IDE. Sorry.
if (obj.find(srcDir) == 0) {
obj = this->ConvertPath(obj, true);
- this->ConvertToWindowsSlash(obj);
+ ConvertToWindowsSlash(obj);
useRelativePath = true;
}
}
@@ -741,10 +717,8 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h";
(*this->BuildFileStream) << hFileName << "</DependentUpon>\n";
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- this->WritePlatformConfigTag("LogicalName", *i, 3);
+ for (std::string const& i : this->Configurations) {
+ this->WritePlatformConfigTag("LogicalName", i, 3);
if (this->GeneratorTarget->GetProperty("VS_GLOBAL_ROOTNAMESPACE") ||
// Handle variant of VS_GLOBAL_<variable> for RootNamespace.
this->GeneratorTarget->GetProperty("VS_GLOBAL_RootNamespace")) {
@@ -756,7 +730,7 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
}
} else {
std::string binDir = this->Makefile->GetCurrentBinaryDirectory();
- this->ConvertToWindowsSlash(binDir);
+ ConvertToWindowsSlash(binDir);
// If the resource was NOT added using a relative path (which should
// be the default), we have to provide a link here
if (!useRelativePath) {
@@ -775,13 +749,12 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
}
// Determine if this is a generated resource from a .Designer.cs file
std::string designerResource =
- cmSystemTools::GetFilenamePath((*oi)->GetFullPath()) + "/" +
- cmSystemTools::GetFilenameWithoutLastExtension(
- (*oi)->GetFullPath()) +
+ cmSystemTools::GetFilenamePath(oi->GetFullPath()) + "/" +
+ cmSystemTools::GetFilenameWithoutLastExtension(oi->GetFullPath()) +
".Designer.cs";
if (cmsys::SystemTools::FileExists(designerResource)) {
std::string generator = "PublicResXFileCodeGenerator";
- if (const char* g = (*oi)->GetProperty("VS_RESOURCE_GENERATOR")) {
+ if (const char* g = oi->GetProperty("VS_RESOURCE_GENERATOR")) {
generator = g;
}
if (!generator.empty()) {
@@ -796,20 +769,19 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup()
designerResource =
cmsys::SystemTools::GetFilenameName(designerResource);
}
- this->ConvertToWindowsSlash(designerResource);
+ ConvertToWindowsSlash(designerResource);
this->WriteString("<LastGenOutput>", 3);
(*this->BuildFileStream) << designerResource
<< "</LastGenOutput>\n";
}
}
- const cmPropertyMap& props = (*oi)->GetProperties();
- for (cmPropertyMap::const_iterator p = props.begin(); p != props.end();
- ++p) {
+ const cmPropertyMap& props = oi->GetProperties();
+ for (const auto& p : props) {
static const std::string propNamePrefix = "VS_CSHARP_";
- if (p->first.find(propNamePrefix) == 0) {
- std::string tagName = p->first.substr(propNamePrefix.length());
+ if (p.first.find(propNamePrefix) == 0) {
+ std::string tagName = p.first.substr(propNamePrefix.length());
if (!tagName.empty()) {
- std::string value = props.GetPropertyValue(p->first);
+ std::string value = props.GetPropertyValue(p.first);
if (!value.empty()) {
this->WriteString("<", 3);
(*this->BuildFileStream) << tagName << ">";
@@ -833,19 +805,17 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
this->GeneratorTarget->GetXamlSources(xamlObjs, "");
if (!xamlObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<cmSourceFile const*>::const_iterator oi =
- xamlObjs.begin();
- oi != xamlObjs.end(); ++oi) {
- std::string obj = (*oi)->GetFullPath();
+ for (cmSourceFile const* oi : xamlObjs) {
+ std::string obj = oi->GetFullPath();
std::string xamlType;
- const char* xamlTypeProperty = (*oi)->GetProperty("VS_XAML_TYPE");
+ const char* xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE");
if (xamlTypeProperty) {
xamlType = xamlTypeProperty;
} else {
xamlType = "Page";
}
- this->WriteSource(xamlType, *oi, ">\n");
+ this->WriteSource(xamlType, oi, ">\n");
if (this->ProjectType == csproj && !this->InSourceBuild) {
// add <Link> tag to written XAML source if necessary
const std::string srcDir = this->Makefile->GetCurrentSourceDirectory();
@@ -859,7 +829,7 @@ void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup()
link = cmsys::SystemTools::GetFilenameName(obj);
}
if (!link.empty()) {
- this->ConvertToWindowsSlash(link);
+ ConvertToWindowsSlash(link);
this->WriteString("<Link>", 3);
(*this->BuildFileStream) << link << "</Link>\n";
}
@@ -1087,7 +1057,7 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
}
std::string outDir = this->GeneratorTarget->GetDirectory(config) + "/";
- this->ConvertToWindowsSlash(outDir);
+ ConvertToWindowsSlash(outDir);
this->WriteString("<OutputPath>", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(outDir) << "</OutputPath>\n";
@@ -1174,6 +1144,15 @@ void cmVisualStudio10TargetGenerator::WriteCustomCommands()
si != customCommands.end(); ++si) {
this->WriteCustomCommand(*si);
}
+
+ // Add CMakeLists.txt file with rule to re-run CMake for user convenience.
+ if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET &&
+ this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) {
+ if (cmSourceFile const* sf =
+ this->LocalGenerator->CreateVCProjBuildRule()) {
+ this->WriteCustomCommand(sf);
+ }
+ }
}
void cmVisualStudio10TargetGenerator::WriteCustomCommand(
@@ -1258,7 +1237,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
d != ccg.GetDepends().end(); ++d) {
std::string dep;
if (this->LocalGenerator->GetRealDependency(*d, *i, dep)) {
- this->ConvertToWindowsSlash(dep);
+ ConvertToWindowsSlash(dep);
inputs << ";" << cmVS10EscapeXML(dep);
}
}
@@ -1268,7 +1247,7 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
for (std::vector<std::string>::const_iterator o = ccg.GetOutputs().begin();
o != ccg.GetOutputs().end(); ++o) {
std::string out = *o;
- this->ConvertToWindowsSlash(out);
+ ConvertToWindowsSlash(out);
outputs << sep << cmVS10EscapeXML(out);
sep = ";";
}
@@ -1346,7 +1325,7 @@ std::string cmVisualStudio10TargetGenerator::ConvertPath(
: path.c_str();
}
-void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
+static void ConvertToWindowsSlash(std::string& s)
{
// first convert all of the slashes
std::string::size_type pos = 0;
@@ -1373,7 +1352,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
si != sources.end(); ++si) {
std::string const& source = si->Source->GetFullPath();
cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
+ this->Makefile->FindSourceGroup(source, sourceGroups);
groupsUsed.insert(sourceGroup);
}
@@ -1383,7 +1362,8 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
path += "/";
path += this->Name;
- path += computeProjectFileExtension(this->GeneratorTarget);
+ path += computeProjectFileExtension(this->GeneratorTarget,
+ *this->Configurations.begin());
path += ".filters";
cmGeneratedFileStream fout(path.c_str());
fout.SetCopyIfDifferent(true);
@@ -1410,30 +1390,28 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
// Added files are images and the manifest.
if (!this->AddedFiles.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<std::string>::const_iterator oi =
- this->AddedFiles.begin();
- oi != this->AddedFiles.end(); ++oi) {
+ for (std::string const& oi : this->AddedFiles) {
std::string fileName =
- cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(*oi));
+ cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(oi));
if (fileName == "wmappmanifest.xml") {
this->WriteString("<XML Include=\"", 2);
- (*this->BuildFileStream) << *oi << "\">\n";
+ (*this->BuildFileStream) << oi << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</XML>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) ==
".appxmanifest") {
this->WriteString("<AppxManifest Include=\"", 2);
- (*this->BuildFileStream) << *oi << "\">\n";
+ (*this->BuildFileStream) << oi << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</AppxManifest>\n", 2);
} else if (cmSystemTools::GetFilenameExtension(fileName) == ".pfx") {
this->WriteString("<None Include=\"", 2);
- (*this->BuildFileStream) << *oi << "\">\n";
+ (*this->BuildFileStream) << oi << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</None>\n", 2);
} else {
this->WriteString("<Image Include=\"", 2);
- (*this->BuildFileStream) << *oi << "\">\n";
+ (*this->BuildFileStream) << oi << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</Image>\n", 2);
}
@@ -1445,12 +1423,10 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->GeneratorTarget->GetResxSources(resxObjs, "");
if (!resxObjs.empty()) {
this->WriteString("<ItemGroup>\n", 1);
- for (std::vector<cmSourceFile const*>::const_iterator oi =
- resxObjs.begin();
- oi != resxObjs.end(); ++oi) {
- std::string obj = (*oi)->GetFullPath();
+ for (cmSourceFile const* oi : resxObjs) {
+ std::string obj = oi->GetFullPath();
this->WriteString("<EmbeddedResource Include=\"", 2);
- this->ConvertToWindowsSlash(obj);
+ ConvertToWindowsSlash(obj);
(*this->BuildFileStream) << cmVS10EscapeXML(obj) << "\">\n";
this->WriteString("<Filter>Resource Files</Filter>\n", 3);
this->WriteString("</EmbeddedResource>\n", 2);
@@ -1459,11 +1435,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_";
@@ -1504,16 +1483,15 @@ void cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups)
{
- for (std::vector<cmSourceGroup>::const_iterator current = allGroups.begin();
- current != allGroups.end(); ++current) {
- std::vector<cmSourceGroup> const& children = current->GetGroupChildren();
+ for (cmSourceGroup const& current : allGroups) {
+ std::vector<cmSourceGroup> const& children = current.GetGroupChildren();
if (children.empty()) {
continue; // the group is really empty
}
this->AddMissingSourceGroups(groupsUsed, children);
- cmSourceGroup* current_ptr = const_cast<cmSourceGroup*>(&(*current));
+ cmSourceGroup* current_ptr = const_cast<cmSourceGroup*>(&current);
if (groupsUsed.find(current_ptr) != groupsUsed.end()) {
continue; // group has already been added to set
}
@@ -1542,18 +1520,17 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources(
std::vector<cmSourceGroup>& sourceGroups)
{
this->WriteString("<ItemGroup>\n", 1);
- for (ToolSources::const_iterator s = sources.begin(); s != sources.end();
- ++s) {
- cmSourceFile const* sf = s->SourceFile;
+ for (ToolSource const& s : sources) {
+ cmSourceFile const* sf = s.SourceFile;
std::string const& source = sf->GetFullPath();
cmSourceGroup* sourceGroup =
- this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
- const char* filter = sourceGroup->GetFullName();
+ this->Makefile->FindSourceGroup(source, sourceGroups);
+ std::string const& filter = sourceGroup->GetFullName();
this->WriteString("<", 2);
- std::string path = this->ConvertPath(source, s->RelativePath);
- this->ConvertToWindowsSlash(path);
+ std::string path = this->ConvertPath(source, s.RelativePath);
+ 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";
@@ -1592,6 +1569,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
std::string shaderEntryPoint;
std::string shaderModel;
std::string shaderAdditionalFlags;
+ std::string shaderDisableOptimizations;
+ std::string shaderEnableDebug;
std::string outputHeaderFile;
std::string variableName;
std::string settingsGenerator;
@@ -1622,7 +1601,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
sourceLink = cmsys::SystemTools::GetFilenameName(fullFileName);
}
if (!sourceLink.empty()) {
- this->ConvertToWindowsSlash(sourceLink);
+ ConvertToWindowsSlash(sourceLink);
}
}
}
@@ -1658,6 +1637,16 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
shaderAdditionalFlags = saf;
toolHasSettings = true;
}
+ // Figure out if debug information should be generated
+ if (const char* sed = sf->GetProperty("VS_SHADER_ENABLE_DEBUG")) {
+ shaderEnableDebug = cmSystemTools::IsOn(sed) ? "true" : "false";
+ toolHasSettings = true;
+ }
+ // Figure out if optimizations should be disabled
+ if (const char* sdo = sf->GetProperty("VS_SHADER_DISABLE_OPTIMIZATIONS")) {
+ shaderDisableOptimizations = cmSystemTools::IsOn(sdo) ? "true" : "false";
+ toolHasSettings = true;
+ }
} else if (ext == "jpg" || ext == "png") {
tool = "Image";
} else if (ext == "resw") {
@@ -1667,12 +1656,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
} else if (ext == "natvis") {
tool = "Natvis";
} else if (ext == "settings") {
- // remove path to current source dir (if files are in current source dir)
- if (!sourceLink.empty()) {
- settingsLastGenOutput = sourceLink;
- } else {
- settingsLastGenOutput = sf->GetFullPath();
- }
+ settingsLastGenOutput =
+ cmsys::SystemTools::GetFilenameName(sf->GetFullPath());
std::size_t pos = settingsLastGenOutput.find(".settings");
settingsLastGenOutput.replace(pos, 9, ".Designer.cs");
settingsGenerator = "SettingsSingleFileGenerator";
@@ -1800,6 +1785,16 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf)
this->WriteString("</VariableName>\n", 0);
}
}
+ if (!shaderEnableDebug.empty()) {
+ this->WriteString("<EnableDebuggingInformation>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderEnableDebug)
+ << "</EnableDebuggingInformation>\n";
+ }
+ if (!shaderDisableOptimizations.empty()) {
+ this->WriteString("<DisableOptimizations>", 3);
+ (*this->BuildFileStream) << cmVS10EscapeXML(shaderDisableOptimizations)
+ << "</DisableOptimizations>\n";
+ }
if (!shaderAdditionalFlags.empty()) {
this->WriteString("<AdditionalOptions>", 3);
(*this->BuildFileStream) << cmVS10EscapeXML(shaderAdditionalFlags)
@@ -1878,7 +1873,7 @@ void cmVisualStudio10TargetGenerator::WriteSource(std::string const& tool,
this->GlobalGenerator->PathTooLong(this->GeneratorTarget, sf, sourceRel);
}
}
- this->ConvertToWindowsSlash(sourceFile);
+ ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
(*this->BuildFileStream) << tool << " Include=\""
<< cmVS10EscapeXML(sourceFile) << "\""
@@ -1903,11 +1898,9 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
std::vector<cmGeneratorTarget::AllConfigSource> const& sources =
this->GeneratorTarget->GetAllConfigSources();
- for (std::vector<cmGeneratorTarget::AllConfigSource>::const_iterator si =
- sources.begin();
- si != sources.end(); ++si) {
+ for (cmGeneratorTarget::AllConfigSource const& si : sources) {
std::string tool;
- switch (si->Kind) {
+ switch (si.Kind) {
case cmGeneratorTarget::SourceKindAppManifest:
tool = "AppxManifest";
break;
@@ -1926,17 +1919,17 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
// then vs10 will use it in the build, and we have to list it as
// None instead of Object.
std::vector<cmSourceFile*> const* d =
- this->GeneratorTarget->GetSourceDepends(si->Source);
+ this->GeneratorTarget->GetSourceDepends(si.Source);
if (d && !d->empty()) {
tool = "None";
}
}
break;
case cmGeneratorTarget::SourceKindExtra:
- this->WriteExtraSource(si->Source);
+ this->WriteExtraSource(si.Source);
break;
case cmGeneratorTarget::SourceKindHeader:
- this->WriteHeaderSource(si->Source);
+ this->WriteHeaderSource(si.Source);
break;
case cmGeneratorTarget::SourceKindIDL:
tool = "Midl";
@@ -1948,7 +1941,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
tool = "None";
break;
case cmGeneratorTarget::SourceKindObjectSource: {
- const std::string& lang = si->Source->GetLanguage();
+ const std::string& lang = si.Source->GetLanguage();
if (lang == "C" || lang == "CXX") {
tool = "ClCompile";
} else if (lang == "ASM_MASM" &&
@@ -1977,16 +1970,16 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
if (!tool.empty()) {
// Compute set of configurations to exclude, if any.
- std::vector<size_t> const& include_configs = si->Configs;
+ std::vector<size_t> const& include_configs = si.Configs;
std::vector<size_t> exclude_configs;
std::set_difference(all_configs.begin(), all_configs.end(),
include_configs.begin(), include_configs.end(),
std::back_inserter(exclude_configs));
- if (si->Kind == cmGeneratorTarget::SourceKindObjectSource) {
+ if (si.Kind == cmGeneratorTarget::SourceKindObjectSource) {
// FIXME: refactor generation to avoid tracking XML syntax state.
- this->WriteSource(tool, si->Source, " ");
- bool have_nested = this->OutputSourceSpecificFlags(si->Source);
+ this->WriteSource(tool, si.Source, "");
+ bool have_nested = this->OutputSourceSpecificFlags(si.Source);
if (!exclude_configs.empty()) {
if (!have_nested) {
(*this->BuildFileStream) << ">\n";
@@ -2001,12 +1994,12 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
(*this->BuildFileStream) << " />\n";
}
} else if (!exclude_configs.empty()) {
- this->WriteSource(tool, si->Source, ">\n");
+ this->WriteSource(tool, si.Source, ">\n");
this->WriteExcludeFromBuild(exclude_configs);
this->WriteString("</", 2);
(*this->BuildFileStream) << tool << ">\n";
} else {
- this->WriteSource(tool, si->Source);
+ this->WriteSource(tool, si.Source);
}
}
}
@@ -2029,17 +2022,32 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
}
std::string flags;
bool configDependentFlags = false;
+ std::string options;
+ bool configDependentOptions = false;
std::string defines;
+ bool configDependentDefines = false;
+ std::string includes;
+ bool configDependentIncludes = false;
if (const char* cflags = sf.GetProperty("COMPILE_FLAGS")) {
-
- if (cmGeneratorExpression::Find(cflags) != std::string::npos) {
- configDependentFlags = true;
- }
+ configDependentFlags =
+ cmGeneratorExpression::Find(cflags) != std::string::npos;
flags += cflags;
}
+ if (const char* coptions = sf.GetProperty("COMPILE_OPTIONS")) {
+ configDependentOptions =
+ cmGeneratorExpression::Find(coptions) != std::string::npos;
+ options += coptions;
+ }
if (const char* cdefs = sf.GetProperty("COMPILE_DEFINITIONS")) {
+ configDependentDefines =
+ cmGeneratorExpression::Find(cdefs) != std::string::npos;
defines += cdefs;
}
+ if (const char* cincludes = sf.GetProperty("INCLUDE_DIRECTORIES")) {
+ configDependentIncludes =
+ cmGeneratorExpression::Find(cincludes) != std::string::npos;
+ includes += cincludes;
+ }
std::string lang =
this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str());
std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf);
@@ -2072,14 +2080,18 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
(*this->BuildFileStream) << firstString;
firstString = "";
hasFlags = true;
- this->WriteString("<ObjectFileName>", 3);
- (*this->BuildFileStream) << "$(IntDir)/" << objectName
- << "</ObjectFileName>\n";
+ if (lang == "CUDA") {
+ this->WriteString("<CompileOut>", 3);
+ (*this->BuildFileStream) << "$(IntDir)/" << objectName
+ << "</CompileOut>\n";
+ } else {
+ this->WriteString("<ObjectFileName>", 3);
+ (*this->BuildFileStream) << "$(IntDir)/" << objectName
+ << "</ObjectFileName>\n";
+ }
}
- for (std::vector<std::string>::const_iterator config =
- this->Configurations.begin();
- config != this->Configurations.end(); ++config) {
- std::string configUpper = cmSystemTools::UpperCase(*config);
+ for (std::string const& config : this->Configurations) {
+ std::string configUpper = cmSystemTools::UpperCase(config);
std::string configDefines = defines;
std::string defPropName = "COMPILE_DEFINITIONS_";
defPropName += configUpper;
@@ -2087,12 +2099,14 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
if (!configDefines.empty()) {
configDefines += ";";
}
+ configDependentDefines |=
+ cmGeneratorExpression::Find(ccdefs) != std::string::npos;
configDefines += ccdefs;
}
// if we have flags or defines for this config then
// use them
- if (!flags.empty() || configDependentFlags || !configDefines.empty() ||
- compileAs || noWinRT) {
+ if (!flags.empty() || !options.empty() || !configDefines.empty() ||
+ !includes.empty() || compileAs || noWinRT) {
(*this->BuildFileStream) << firstString;
firstString = ""; // only do firstString once
hasFlags = true;
@@ -2113,6 +2127,9 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
} else if (srclang == "CSharp") {
flagtable = gg->GetCSharpFlagTable();
}
+ cmGeneratorExpressionInterpreter genexInterpreter(
+ this->LocalGenerator, this->GeneratorTarget, config,
+ this->GeneratorTarget->GetName(), lang);
cmVisualStudioGeneratorOptions clOptions(
this->LocalGenerator, cmVisualStudioGeneratorOptions::Compiler,
flagtable, 0, this);
@@ -2123,25 +2140,45 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
clOptions.AddFlag("CompileAsWinRT", "false");
}
if (configDependentFlags) {
- cmGeneratorExpression ge;
- std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(flags);
- std::string evaluatedFlags = cge->Evaluate(
- this->LocalGenerator, *config, false, this->GeneratorTarget);
- clOptions.Parse(evaluatedFlags.c_str());
+ clOptions.Parse(genexInterpreter.Evaluate(flags, "COMPILE_FLAGS"));
} else {
clOptions.Parse(flags.c_str());
}
- if (clOptions.HasFlag("AdditionalIncludeDirectories")) {
- clOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
+ if (!options.empty()) {
+ std::string expandedOptions;
+ if (configDependentOptions) {
+ this->LocalGenerator->AppendCompileOptions(
+ expandedOptions,
+ genexInterpreter.Evaluate(options, "COMPILE_OPTIONS"));
+ } else {
+ this->LocalGenerator->AppendCompileOptions(expandedOptions, options);
+ }
+ clOptions.Parse(expandedOptions.c_str());
}
if (clOptions.HasFlag("DisableSpecificWarnings")) {
clOptions.AppendFlag("DisableSpecificWarnings",
"%(DisableSpecificWarnings)");
}
- clOptions.AddDefines(configDefines.c_str());
- clOptions.SetConfiguration((*config).c_str());
+ if (configDependentDefines) {
+ clOptions.AddDefines(
+ genexInterpreter.Evaluate(configDefines, "COMPILE_DEFINITIONS"));
+ } else {
+ clOptions.AddDefines(configDefines.c_str());
+ }
+ std::vector<std::string> includeList;
+ if (configDependentIncludes) {
+ this->LocalGenerator->AppendIncludeDirectories(
+ includeList,
+ genexInterpreter.Evaluate(includes, "INCLUDE_DIRECTORIES"), *source);
+ } else {
+ this->LocalGenerator->AppendIncludeDirectories(includeList, includes,
+ *source);
+ }
+ clOptions.AddIncludes(includeList);
+ clOptions.SetConfiguration(config.c_str());
clOptions.PrependInheritedString("AdditionalOptions");
+ clOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+ " ", "\n", lang);
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", lang);
@@ -2182,12 +2219,11 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
void cmVisualStudio10TargetGenerator::WriteExcludeFromBuild(
std::vector<size_t> const& exclude_configs)
{
- for (std::vector<size_t>::const_iterator ci = exclude_configs.begin();
- ci != exclude_configs.end(); ++ci) {
+ for (size_t ci : exclude_configs) {
this->WriteString("", 3);
(*this->BuildFileStream)
<< "<ExcludedFromBuild Condition=\"'$(Configuration)|$(Platform)'=='"
- << cmVS10EscapeXML(this->Configurations[*ci]) << "|"
+ << cmVS10EscapeXML(this->Configurations[ci]) << "|"
<< cmVS10EscapeXML(this->Platform) << "'\">true</ExcludedFromBuild>\n";
}
}
@@ -2206,11 +2242,9 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
this->WriteString("<_ProjectFileVersion>10.0.20506.1"
"</_ProjectFileVersion>\n",
2);
- for (std::vector<std::string>::const_iterator config =
- this->Configurations.begin();
- config != this->Configurations.end(); ++config) {
+ for (std::string const& config : this->Configurations) {
if (ttype >= cmStateEnums::UTILITY) {
- this->WritePlatformConfigTag("IntDir", *config, 2);
+ this->WritePlatformConfigTag("IntDir", config, 2);
*this->BuildFileStream
<< "$(Platform)\\$(Configuration)\\$(ProjectName)\\"
<< "</IntDir>\n";
@@ -2218,7 +2252,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
std::string intermediateDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
intermediateDir += "/";
- intermediateDir += *config;
+ intermediateDir += config;
intermediateDir += "/";
std::string outDir;
std::string targetNameFull;
@@ -2227,22 +2261,22 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
targetNameFull = this->GeneratorTarget->GetName();
targetNameFull += ".lib";
} else {
- outDir = this->GeneratorTarget->GetDirectory(*config) + "/";
- targetNameFull = this->GeneratorTarget->GetFullName(*config);
+ outDir = this->GeneratorTarget->GetDirectory(config) + "/";
+ targetNameFull = this->GeneratorTarget->GetFullName(config);
}
- this->ConvertToWindowsSlash(intermediateDir);
- this->ConvertToWindowsSlash(outDir);
+ ConvertToWindowsSlash(intermediateDir);
+ ConvertToWindowsSlash(outDir);
- this->WritePlatformConfigTag("OutDir", *config, 2);
+ this->WritePlatformConfigTag("OutDir", config, 2);
*this->BuildFileStream << cmVS10EscapeXML(outDir) << "</OutDir>\n";
- this->WritePlatformConfigTag("IntDir", *config, 2);
+ this->WritePlatformConfigTag("IntDir", config, 2);
*this->BuildFileStream << cmVS10EscapeXML(intermediateDir)
<< "</IntDir>\n";
if (const char* workingDir = this->GeneratorTarget->GetProperty(
"VS_DEBUGGER_WORKING_DIRECTORY")) {
- this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", *config,
+ this->WritePlatformConfigTag("LocalDebuggerWorkingDirectory", config,
2);
*this->BuildFileStream << cmVS10EscapeXML(workingDir)
<< "</LocalDebuggerWorkingDirectory>\n";
@@ -2250,7 +2284,7 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
std::string name =
cmSystemTools::GetFilenameWithoutLastExtension(targetNameFull);
- this->WritePlatformConfigTag("TargetName", *config, 2);
+ this->WritePlatformConfigTag("TargetName", config, 2);
*this->BuildFileStream << cmVS10EscapeXML(name) << "</TargetName>\n";
std::string ext =
@@ -2260,10 +2294,10 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions()
// A single "." appears to be treated as an empty extension.
ext = ".";
}
- this->WritePlatformConfigTag("TargetExt", *config, 2);
+ this->WritePlatformConfigTag("TargetExt", config, 2);
*this->BuildFileStream << cmVS10EscapeXML(ext) << "</TargetExt>\n";
- this->OutputLinkIncremental(*config);
+ this->OutputLinkIncremental(config);
}
}
this->WriteString("</PropertyGroup>\n", 1);
@@ -2311,12 +2345,22 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental(
}
}
+std::vector<std::string> cmVisualStudio10TargetGenerator::GetIncludes(
+ std::string const& config, std::string const& lang) const
+{
+ std::vector<std::string> includes;
+ this->LocalGenerator->GetIncludeDirectories(includes, this->GeneratorTarget,
+ lang, config);
+ for (std::string& i : includes) {
+ ConvertToWindowsSlash(i);
+ }
+ return includes;
+}
+
bool cmVisualStudio10TargetGenerator::ComputeClOptions()
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeClOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeClOptions(i)) {
return false;
}
}
@@ -2359,20 +2403,21 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
// Choose a language whose flags to use for ClCompile.
static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
std::string langForClCompile;
- if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
- cmArrayEnd(clLangs)) {
+ if (std::find(cm::cbegin(clLangs), cm::cend(clLangs), linkLanguage) !=
+ cm::cend(clLangs)) {
langForClCompile = linkLanguage;
} else {
std::set<std::string> languages;
this->GeneratorTarget->GetLanguages(languages, configName);
- for (const char* const* l = cmArrayBegin(clLangs);
- l != cmArrayEnd(clLangs); ++l) {
+ for (const char* const* l = cm::cbegin(clLangs); l != cm::cend(clLangs);
+ ++l) {
if (languages.find(*l) != languages.end()) {
langForClCompile = *l;
break;
}
}
}
+ this->LangForClCompile = langForClCompile;
if (!langForClCompile.empty()) {
std::string baseFlagVar = "CMAKE_";
baseFlagVar += langForClCompile;
@@ -2408,7 +2453,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.FixExceptionHandlingDefault();
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
std::string asmLocation = configName + "/";
- clOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str());
+ clOptions.AddFlag("AssemblerListingLocation", asmLocation);
}
}
clOptions.Parse(flags.c_str());
@@ -2416,8 +2461,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
std::vector<std::string> targetDefines;
switch (this->ProjectType) {
case vcxproj:
- this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
- "CXX");
+ if (!langForClCompile.empty()) {
+ this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
+ langForClCompile);
+ }
break;
case csproj:
this->GeneratorTarget->GetCompileDefinitions(targetDefines, configName,
@@ -2425,6 +2472,13 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
break;
}
clOptions.AddDefines(targetDefines);
+
+ // Get includes for this target
+ if (!this->LangForClCompile.empty()) {
+ clOptions.AddIncludes(
+ this->GetIncludes(configName, this->LangForClCompile));
+ }
+
if (this->MSTools) {
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -2476,12 +2530,12 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
}
}
- this->ClOptions[configName] = pOptions.release();
+ this->ClOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteClOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ std::string const& configName)
{
Options& clOptions = *(this->ClOptions[configName]);
if (this->ProjectType == csproj) {
@@ -2489,12 +2543,11 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
}
this->WriteString("<ClCompile>\n", 2);
clOptions.PrependInheritedString("AdditionalOptions");
- clOptions.AppendFlag("AdditionalIncludeDirectories", includes);
- clOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
+ clOptions.OutputAdditionalIncludeDirectories(
+ *this->BuildFileStream, " ", "\n", this->LangForClCompile);
clOptions.OutputFlagMap(*this->BuildFileStream, " ");
clOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
- "\n", "CXX");
+ "\n", this->LangForClCompile);
if (this->NsightTegra) {
if (const char* processMax =
@@ -2518,17 +2571,18 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
}
// If not in debug mode, write the DebugInformationFormat field
- // without value so PDBs don't get generated uselessly.
+ // without value so PDBs don't get generated uselessly. Each tag
+ // goes on its own line because Visual Studio corrects it this
+ // way when saving the project after CMake generates it.
if (!clOptions.IsDebug()) {
- this->WriteString("<DebugInformationFormat>"
- "</DebugInformationFormat>\n",
- 3);
+ this->WriteString("<DebugInformationFormat>\n", 3);
+ this->WriteString("</DebugInformationFormat>\n", 3);
}
// Specify the compiler program database file if configured.
std::string pdb = this->GeneratorTarget->GetCompilePDBPath(configName);
if (!pdb.empty()) {
- this->ConvertToWindowsSlash(pdb);
+ ConvertToWindowsSlash(pdb);
this->WriteString("<ProgramDataBaseFileName>", 3);
*this->BuildFileStream << cmVS10EscapeXML(pdb)
<< "</ProgramDataBaseFileName>\n";
@@ -2540,10 +2594,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
bool cmVisualStudio10TargetGenerator::ComputeRcOptions()
{
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeRcOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeRcOptions(i)) {
return false;
}
}
@@ -2572,12 +2624,15 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions(
Options& clOptions = *(this->ClOptions[configName]);
rcOptions.AddDefines(clOptions.GetDefines());
- this->RcOptions[configName] = pOptions.release();
+ // Get includes for this target
+ rcOptions.AddIncludes(this->GetIncludes(configName, "RC"));
+
+ this->RcOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteRCOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ std::string const& configName)
{
if (!this->MSTools) {
return;
@@ -2587,9 +2642,8 @@ void cmVisualStudio10TargetGenerator::WriteRCOptions(
Options& rcOptions = *(this->RcOptions[configName]);
rcOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "RC");
- rcOptions.AppendFlag("AdditionalIncludeDirectories", includes);
- rcOptions.AppendFlag("AdditionalIncludeDirectories",
- "%(AdditionalIncludeDirectories)");
+ rcOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+ " ", "\n", "RC");
rcOptions.PrependInheritedString("AdditionalOptions");
rcOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -2601,10 +2655,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeCudaOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeCudaOptions(i)) {
return false;
}
}
@@ -2638,6 +2690,18 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
cudaOptions.Parse(defineFlags.c_str());
cudaOptions.ParseFinish();
+ // If we haven't explicitly enabled GPU debug information
+ // explicitly disable it
+ if (!cudaOptions.HasFlag("GPUDebugInfo")) {
+ cudaOptions.AddFlag("GPUDebugInfo", "false");
+ }
+
+ // The extension on object libraries the CUDA gives isn't
+ // consistent with how MSVC generates object libraries for C+, so set
+ // the default to not have any extension
+ cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).obj");
+
+ bool notPtx = true;
if (this->GeneratorTarget->GetPropertyAsBool("CUDA_SEPARABLE_COMPILATION")) {
cudaOptions.AddFlag("GenerateRelocatableDeviceCode", "true");
} else if (this->GeneratorTarget->GetPropertyAsBool(
@@ -2646,6 +2710,16 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
// We drop the %(Extension) component as CMake expects all PTX files
// to not have the source file extension at all
cudaOptions.AddFlag("CompileOut", "$(IntDir)%(Filename).ptx");
+ notPtx = false;
+ }
+
+ if (notPtx &&
+ cmSystemTools::VersionCompareGreaterEq(
+ "8.0", this->GlobalGenerator->GetPlatformToolsetCudaString())) {
+ // Explicitly state that we want this file to be treated as a
+ // CUDA file no matter what the file extensions is
+ // This is only needed for < CUDA 9
+ cudaOptions.AppendFlagString("AdditionalOptions", "-x cu");
}
// CUDA automatically passes the proper '--machine' flag to nvcc
@@ -2688,12 +2762,15 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
cudaOptions.AddDefine(exportMacro);
}
- this->CudaOptions[configName] = pOptions.release();
+ // Get includes for this target
+ cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA"));
+
+ this->CudaOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteCudaOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsCudaEnabled()) {
return;
@@ -2701,8 +2778,8 @@ void cmVisualStudio10TargetGenerator::WriteCudaOptions(
this->WriteString("<CudaCompile>\n", 2);
Options& cudaOptions = *(this->CudaOptions[configName]);
- cudaOptions.AppendFlag("Include", includes);
- cudaOptions.AppendFlag("Include", "%(Include)");
+ cudaOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+ " ", "\n", "CUDA");
cudaOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
"\n", "CUDA");
cudaOptions.PrependInheritedString("AdditionalOptions");
@@ -2716,10 +2793,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions()
if (!this->GlobalGenerator->IsCudaEnabled()) {
return true;
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeCudaLinkOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeCudaLinkOptions(i)) {
return false;
}
}
@@ -2761,7 +2836,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
"-Wno-deprecated-gpu-targets");
}
- this->CudaLinkOptions[configName] = pOptions.release();
+ this->CudaLinkOptions[configName] = std::move(pOptions);
return true;
}
@@ -2787,10 +2862,8 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions()
if (!this->GlobalGenerator->IsMasmEnabled()) {
return true;
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeMasmOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeMasmOptions(i)) {
return false;
}
}
@@ -2814,12 +2887,16 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions(
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
masmOptions.Parse(flags.c_str());
- this->MasmOptions[configName] = pOptions.release();
+
+ // Get includes for this target
+ masmOptions.AddIncludes(this->GetIncludes(configName, "ASM_MASM"));
+
+ this->MasmOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteMasmOptions(
- std::string const& configName, std::vector<std::string> const& includes)
+ std::string const& configName)
{
if (!this->MSTools || !this->GlobalGenerator->IsMasmEnabled()) {
return;
@@ -2832,8 +2909,8 @@ void cmVisualStudio10TargetGenerator::WriteMasmOptions(
"\n", "ASM_MASM");
Options& masmOptions = *(this->MasmOptions[configName]);
- masmOptions.AppendFlag("IncludePaths", includes);
- masmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+ masmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+ " ", "\n", "ASM_MASM");
masmOptions.PrependInheritedString("AdditionalOptions");
masmOptions.OutputFlagMap(*this->BuildFileStream, " ");
@@ -2845,10 +2922,8 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions()
if (!this->GlobalGenerator->IsNasmEnabled()) {
return true;
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeNasmOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeNasmOptions(i)) {
return false;
}
}
@@ -2873,25 +2948,27 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions(
std::string(" ") +
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
nasmOptions.Parse(flags.c_str());
- this->NasmOptions[configName] = pOptions.release();
+
+ // Get includes for this target
+ nasmOptions.AddIncludes(this->GetIncludes(configName, "ASM_NASM"));
+
+ this->NasmOptions[configName] = std::move(pOptions);
return true;
}
void cmVisualStudio10TargetGenerator::WriteNasmOptions(
- std::string const& configName, std::vector<std::string> includes)
+ std::string const& configName)
{
if (!this->GlobalGenerator->IsNasmEnabled()) {
return;
}
this->WriteString("<NASM>\n", 2);
+ std::vector<std::string> includes =
+ this->GetIncludes(configName, "ASM_NASM");
Options& nasmOptions = *(this->NasmOptions[configName]);
- for (size_t i = 0; i < includes.size(); i++) {
- includes[i] += "\\";
- }
-
- nasmOptions.AppendFlag("IncludePaths", includes);
- nasmOptions.AppendFlag("IncludePaths", "%(IncludePaths)");
+ nasmOptions.OutputAdditionalIncludeDirectories(*this->BuildFileStream,
+ " ", "\n", "ASM_NASM");
nasmOptions.OutputFlagMap(*this->BuildFileStream, " ");
nasmOptions.PrependInheritedString("AdditionalOptions");
nasmOptions.OutputPreprocessorDefinitions(*this->BuildFileStream, " ",
@@ -2955,11 +3032,9 @@ void cmVisualStudio10TargetGenerator::WriteManifestOptions(
if (!manifest_srcs.empty()) {
this->WriteString("<Manifest>\n", 2);
this->WriteString("<AdditionalManifestFiles>", 3);
- for (std::vector<cmSourceFile const*>::const_iterator mi =
- manifest_srcs.begin();
- mi != manifest_srcs.end(); ++mi) {
- std::string m = this->ConvertPath((*mi)->GetFullPath(), false);
- this->ConvertToWindowsSlash(m);
+ for (cmSourceFile const* mi : manifest_srcs) {
+ std::string m = this->ConvertPath(mi->GetFullPath(), false);
+ ConvertToWindowsSlash(m);
(*this->BuildFileStream) << m << ";";
}
(*this->BuildFileStream) << "</AdditionalManifestFiles>\n";
@@ -2976,12 +3051,10 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
{
std::vector<cmSourceFile const*> extraSources;
this->GeneratorTarget->GetExtraSources(extraSources, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- extraSources.begin();
- si != extraSources.end(); ++si) {
+ for (cmSourceFile const* si : extraSources) {
if ("androidmanifest.xml" ==
- cmSystemTools::LowerCase((*si)->GetLocation().GetName())) {
- rootDir = (*si)->GetLocation().GetDirectory();
+ cmSystemTools::LowerCase(si->GetLocation().GetName())) {
+ rootDir = si->GetLocation().GetDirectory();
break;
}
}
@@ -2992,7 +3065,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
std::string antBuildPath = rootDir;
this->WriteString("<AntBuild>\n", 2);
this->WriteString("<AntBuildPath>", 3);
- this->ConvertToWindowsSlash(antBuildPath);
+ ConvertToWindowsSlash(antBuildPath);
(*this->BuildFileStream) << cmVS10EscapeXML(antBuildPath)
<< "</AntBuildPath>\n";
}
@@ -3079,7 +3152,7 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions(
{
std::string manifest_xml = rootDir + "/AndroidManifest.xml";
- this->ConvertToWindowsSlash(manifest_xml);
+ ConvertToWindowsSlash(manifest_xml);
this->WriteString("<AndroidManifestLocation>", 3);
(*this->BuildFileStream) << cmVS10EscapeXML(manifest_xml)
<< "</AndroidManifestLocation>\n";
@@ -3100,10 +3173,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions()
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE ||
this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeLinkOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeLinkOptions(i)) {
return false;
}
}
@@ -3200,19 +3271,17 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkOptions.AddFlag("AdditionalDependencies", libVec);
// Populate TargetsFileAndConfigsVec
- for (std::vector<std::string>::iterator ti = vsTargetVec.begin();
- ti != vsTargetVec.end(); ++ti) {
- this->AddTargetsFileAndConfigPair(*ti, config);
+ for (std::string const& ti : vsTargetVec) {
+ this->AddTargetsFileAndConfigPair(ti, config);
}
std::vector<std::string> const& ldirs = cli.GetDirectories();
std::vector<std::string> linkDirs;
- for (std::vector<std::string>::const_iterator d = ldirs.begin();
- d != ldirs.end(); ++d) {
+ for (std::string const& d : ldirs) {
// first just full path
- linkDirs.push_back(*d);
+ linkDirs.push_back(d);
// next path with configuration type Debug, Release, etc
- linkDirs.push_back(*d + "/$(Configuration)");
+ linkDirs.push_back(d + "/$(Configuration)");
}
linkDirs.push_back("%(AdditionalLibraryDirectories)");
linkOptions.AddFlag("AdditionalLibraryDirectories", linkDirs);
@@ -3275,8 +3344,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
imLib += "/";
imLib += targetNameImport;
- linkOptions.AddFlag("ImportLibrary", imLib.c_str());
- linkOptions.AddFlag("ProgramDataBaseFile", pdb.c_str());
+ linkOptions.AddFlag("ImportLibrary", imLib);
+ linkOptions.AddFlag("ProgramDataBaseFile", pdb);
// A Windows Runtime component uses internal .NET metadata,
// so does not have an import library.
@@ -3297,7 +3366,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkOptions.AppendFlag("IgnoreSpecificDefaultLibraries", "ole32.lib");
}
} else if (this->NsightTegra) {
- linkOptions.AddFlag("SoName", targetNameSO.c_str());
+ linkOptions.AddFlag("SoName", targetNameSO);
}
linkOptions.Parse(flags.c_str());
@@ -3325,17 +3394,15 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
}
}
- this->LinkOptions[config] = pOptions.release();
+ this->LinkOptions[config] = std::move(pOptions);
return true;
}
bool cmVisualStudio10TargetGenerator::ComputeLibOptions()
{
if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- if (!this->ComputeLibOptions(*i)) {
+ for (std::string const& i : this->Configurations) {
+ if (!this->ComputeLibOptions(i)) {
return false;
}
}
@@ -3360,11 +3427,11 @@ bool cmVisualStudio10TargetGenerator::ComputeLibOptions(
const ItemVector& libs = cli.GetItems();
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
- for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
- if (l->IsPath && cmVS10IsTargetsFile(l->Value)) {
+ for (cmComputeLinkInformation::Item const& l : libs) {
+ if (l.IsPath && cmVS10IsTargetsFile(l.Value)) {
std::string path =
- this->LocalGenerator->ConvertToRelativePath(currentBinDir, l->Value);
- this->ConvertToWindowsSlash(path);
+ this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
+ ConvertToWindowsSlash(path);
this->AddTargetsFileAndConfigPair(path, config);
}
}
@@ -3406,19 +3473,19 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
ItemVector const& libs = cli.GetItems();
std::string currentBinDir =
this->LocalGenerator->GetCurrentBinaryDirectory();
- for (ItemVector::const_iterator l = libs.begin(); l != libs.end(); ++l) {
- if (l->IsPath) {
+ for (cmComputeLinkInformation::Item const& l : libs) {
+ if (l.IsPath) {
std::string path =
- this->LocalGenerator->ConvertToRelativePath(currentBinDir, l->Value);
- this->ConvertToWindowsSlash(path);
- if (cmVS10IsTargetsFile(l->Value)) {
+ this->LocalGenerator->ConvertToRelativePath(currentBinDir, l.Value);
+ ConvertToWindowsSlash(path);
+ if (cmVS10IsTargetsFile(l.Value)) {
vsTargetVec.push_back(path);
} else {
libVec.push_back(path);
}
- } else if (!l->Target ||
- l->Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
- libVec.push_back(l->Value);
+ } else if (!l.Target ||
+ l.Target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
+ libVec.push_back(l.Value);
}
}
}
@@ -3426,13 +3493,11 @@ void cmVisualStudio10TargetGenerator::AddLibraries(
void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
std::string const& targetsFile, std::string const& config)
{
- for (std::vector<TargetsFileAndConfigs>::iterator i =
- this->TargetsFileAndConfigsVec.begin();
- i != this->TargetsFileAndConfigsVec.end(); ++i) {
- if (cmSystemTools::ComparePath(targetsFile, i->File)) {
- if (std::find(i->Configs.begin(), i->Configs.end(), config) ==
- i->Configs.end()) {
- i->Configs.push_back(config);
+ for (TargetsFileAndConfigs& i : this->TargetsFileAndConfigsVec) {
+ if (cmSystemTools::ComparePath(targetsFile, i.File)) {
+ if (std::find(i.Configs.begin(), i.Configs.end(), config) ==
+ i.Configs.end()) {
+ i.Configs.push_back(config);
}
return;
}
@@ -3444,7 +3509,7 @@ void cmVisualStudio10TargetGenerator::AddTargetsFileAndConfigPair(
}
void cmVisualStudio10TargetGenerator::WriteMidlOptions(
- std::string const& /*config*/, std::vector<std::string> const& includes)
+ std::string const& configName)
{
if (!this->MSTools) {
return;
@@ -3470,9 +3535,10 @@ void cmVisualStudio10TargetGenerator::WriteMidlOptions(
// on the CMake side?
this->WriteString("<Midl>\n", 2);
this->WriteString("<AdditionalIncludeDirectories>", 3);
- for (std::vector<std::string>::const_iterator i = includes.begin();
- i != includes.end(); ++i) {
- *this->BuildFileStream << cmVS10EscapeXML(*i) << ";";
+ std::vector<std::string> const includes =
+ this->GetIncludes(configName, "MIDL");
+ for (std::string const& i : includes) {
+ *this->BuildFileStream << cmVS10EscapeXML(i) << ";";
}
this->WriteString("%(AdditionalIncludeDirectories)"
"</AdditionalIncludeDirectories>\n",
@@ -3494,44 +3560,35 @@ void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups()
if (this->ProjectType == csproj) {
return;
}
- for (std::vector<std::string>::const_iterator i =
- this->Configurations.begin();
- i != this->Configurations.end(); ++i) {
- std::vector<std::string> includes;
- this->LocalGenerator->GetIncludeDirectories(
- includes, this->GeneratorTarget, "C", *i);
- for (std::vector<std::string>::iterator ii = includes.begin();
- ii != includes.end(); ++ii) {
- this->ConvertToWindowsSlash(*ii);
- }
- this->WritePlatformConfigTag("ItemDefinitionGroup", *i, 1);
+ for (const auto& i : this->Configurations) {
+ this->WritePlatformConfigTag("ItemDefinitionGroup", i, 1);
*this->BuildFileStream << "\n";
// output cl compile flags <ClCompile></ClCompile>
if (this->GeneratorTarget->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
- this->WriteClOptions(*i, includes);
+ this->WriteClOptions(i);
// output rc compile flags <ResourceCompile></ResourceCompile>
- this->WriteRCOptions(*i, includes);
- this->WriteCudaOptions(*i, includes);
- this->WriteMasmOptions(*i, includes);
- this->WriteNasmOptions(*i, includes);
+ this->WriteRCOptions(i);
+ this->WriteCudaOptions(i);
+ this->WriteMasmOptions(i);
+ this->WriteNasmOptions(i);
}
// output midl flags <Midl></Midl>
- this->WriteMidlOptions(*i, includes);
+ this->WriteMidlOptions(i);
// write events
if (this->ProjectType != csproj) {
- this->WriteEvents(*i);
+ this->WriteEvents(i);
}
// output link flags <Link></Link>
- this->WriteLinkOptions(*i);
- this->WriteCudaLinkOptions(*i);
+ this->WriteLinkOptions(i);
+ this->WriteCudaLinkOptions(i);
// output lib flags <Lib></Lib>
- this->WriteLibOptions(*i);
+ this->WriteLibOptions(i);
// output manifest flags <Manifest></Manifest>
- this->WriteManifestOptions(*i);
+ this->WriteManifestOptions(i);
if (this->NsightTegra &&
this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
this->GeneratorTarget->GetPropertyAsBool("ANDROID_GUI")) {
- this->WriteAntBuildOptions(*i);
+ this->WriteAntBuildOptions(i);
}
this->WriteString("</ItemDefinitionGroup>\n", 1);
}
@@ -3574,9 +3631,8 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
std::string script;
const char* pre = "";
std::string comment;
- for (std::vector<cmCustomCommand>::const_iterator i = commands.begin();
- i != commands.end(); ++i) {
- cmCustomCommandGenerator ccg(*i, configName, this->LocalGenerator);
+ for (cmCustomCommand const& i : commands) {
+ cmCustomCommandGenerator ccg(i, configName, this->LocalGenerator);
if (!ccg.HasOnlyEmptyCommandLines()) {
comment += pre;
comment += lg->ConstructComment(ccg);
@@ -3616,9 +3672,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
OrderedTargetDependSet;
OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET);
this->WriteString("<ItemGroup>\n", 1);
- for (OrderedTargetDependSet::const_iterator i = depends.begin();
- i != depends.end(); ++i) {
- cmGeneratorTarget const* dt = *i;
+ for (cmTargetDepend const& i : depends) {
+ cmGeneratorTarget const* dt = i;
if (dt->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
continue;
}
@@ -3639,9 +3694,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
path = lg->GetCurrentBinaryDirectory();
path += "/";
path += dt->GetName();
- path += computeProjectFileExtension(dt);
+ path += computeProjectFileExtension(dt, *this->Configurations.begin());
}
- this->ConvertToWindowsSlash(path);
+ ConvertToWindowsSlash(path);
(*this->BuildFileStream) << cmVS10EscapeXML(path) << "\">\n";
this->WriteString("<Project>", 3);
(*this->BuildFileStream) << "{" << this->GlobalGenerator->GetGUID(name)
@@ -3713,10 +3768,9 @@ void cmVisualStudio10TargetGenerator::WriteSDKReferences()
cmSystemTools::ExpandListArgument(vsSDKReferences, sdkReferences);
this->WriteString("<ItemGroup>\n", 1);
hasWrittenItemGroup = true;
- for (std::vector<std::string>::iterator ri = sdkReferences.begin();
- ri != sdkReferences.end(); ++ri) {
+ for (std::string const& ri : sdkReferences) {
this->WriteString("<SDKReference Include=\"", 2);
- (*this->BuildFileStream) << cmVS10EscapeXML(*ri) << "\"/>\n";
+ (*this->BuildFileStream) << cmVS10EscapeXML(ri) << "\"/>\n";
}
}
@@ -3771,11 +3825,9 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
std::string pfxFile;
std::vector<cmSourceFile const*> certificates;
this->GeneratorTarget->GetCertificates(certificates, "");
- for (std::vector<cmSourceFile const*>::const_iterator si =
- certificates.begin();
- si != certificates.end(); ++si) {
- pfxFile = this->ConvertPath((*si)->GetFullPath(), false);
- this->ConvertToWindowsSlash(pfxFile);
+ for (cmSourceFile const* si : certificates) {
+ pfxFile = this->ConvertPath(si->GetFullPath(), false);
+ ConvertToWindowsSlash(pfxFile);
break;
}
@@ -3785,7 +3837,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
// Move the manifest to a project directory to avoid clashes
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
this->WriteString("<PropertyGroup>\n", 1);
this->WriteString("<AppxPackageArtifactsDir>", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(artifactDir)
@@ -3793,7 +3845,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
this->WriteString("<ProjectPriFullPath>", 2);
std::string resourcePriFile =
this->DefaultArtifactDir + "/resources.pri";
- this->ConvertToWindowsSlash(resourcePriFile);
+ ConvertToWindowsSlash(resourcePriFile);
(*this->BuildFileStream) << resourcePriFile << "</ProjectPriFullPath>\n";
// If we are missing files and we don't have a certificate and
@@ -3804,7 +3856,7 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile()
pfxFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
cmSystemTools::CopyAFile(templateFolder + "/Windows_TemporaryKey.pfx",
pfxFile, false);
- this->ConvertToWindowsSlash(pfxFile);
+ ConvertToWindowsSlash(pfxFile);
this->AddedFiles.push_back(pfxFile);
}
@@ -3986,12 +4038,10 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles()
std::vector<cmSourceFile const*> extraSources;
this->GeneratorTarget->GetExtraSources(extraSources, "");
bool foundManifest = false;
- for (std::vector<cmSourceFile const*>::const_iterator si =
- extraSources.begin();
- si != extraSources.end(); ++si) {
+ for (cmSourceFile const* si : extraSources) {
// Need to do a lowercase comparison on the filename
if ("wmappmanifest.xml" ==
- cmSystemTools::LowerCase((*si)->GetLocation().GetName())) {
+ cmSystemTools::LowerCase(si->GetLocation().GetName())) {
foundManifest = true;
break;
}
@@ -4050,7 +4100,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
std::string("/WMAppManifest.xml");
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
@@ -4097,7 +4147,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
/* clang-format on */
std::string sourceFile = this->ConvertPath(manifestFile, false);
- this->ConvertToWindowsSlash(sourceFile);
+ ConvertToWindowsSlash(sourceFile);
this->WriteString("<Xml Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
this->WriteString("<SubType>Designer</SubType>\n", 3);
@@ -4107,14 +4157,14 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
- this->ConvertToWindowsSlash(smallLogo);
+ ConvertToWindowsSlash(smallLogo);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
this->AddedFiles.push_back(smallLogo);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
- this->ConvertToWindowsSlash(logo);
+ ConvertToWindowsSlash(logo);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
this->AddedFiles.push_back(logo);
@@ -4123,7 +4173,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP80()
this->DefaultArtifactDir + "/ApplicationIcon.png";
cmSystemTools::CopyAFile(templateFolder + "/ApplicationIcon.png",
applicationIcon, false);
- this->ConvertToWindowsSlash(applicationIcon);
+ ConvertToWindowsSlash(applicationIcon);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(applicationIcon) << "\" />\n";
this->AddedFiles.push_back(applicationIcon);
@@ -4135,7 +4185,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWP81()
this->DefaultArtifactDir + "/package.appxManifest";
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
@@ -4198,7 +4248,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS80()
this->DefaultArtifactDir + "/package.appxManifest";
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
@@ -4253,7 +4303,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS81()
this->DefaultArtifactDir + "/package.appxManifest";
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
@@ -4313,7 +4363,7 @@ void cmVisualStudio10TargetGenerator::WriteMissingFilesWS10_0()
this->DefaultArtifactDir + "/package.appxManifest";
std::string artifactDir =
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
- this->ConvertToWindowsSlash(artifactDir);
+ ConvertToWindowsSlash(artifactDir);
std::string artifactDirXML = cmVS10EscapeXML(artifactDir);
std::string targetNameXML =
cmVS10EscapeXML(this->GeneratorTarget->GetName());
@@ -4375,7 +4425,7 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
cmSystemTools::GetCMakeRoot() + "/Templates/Windows";
std::string sourceFile = this->ConvertPath(manifestFile, false);
- this->ConvertToWindowsSlash(sourceFile);
+ ConvertToWindowsSlash(sourceFile);
this->WriteString("<AppxManifest Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(sourceFile) << "\">\n";
this->WriteString("<SubType>Designer</SubType>\n", 3);
@@ -4385,7 +4435,7 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
std::string smallLogo = this->DefaultArtifactDir + "/SmallLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo.png", smallLogo,
false);
- this->ConvertToWindowsSlash(smallLogo);
+ ConvertToWindowsSlash(smallLogo);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(smallLogo) << "\" />\n";
this->AddedFiles.push_back(smallLogo);
@@ -4393,14 +4443,14 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
std::string smallLogo44 = this->DefaultArtifactDir + "/SmallLogo44x44.png";
cmSystemTools::CopyAFile(templateFolder + "/SmallLogo44x44.png", smallLogo44,
false);
- this->ConvertToWindowsSlash(smallLogo44);
+ ConvertToWindowsSlash(smallLogo44);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(smallLogo44) << "\" />\n";
this->AddedFiles.push_back(smallLogo44);
std::string logo = this->DefaultArtifactDir + "/Logo.png";
cmSystemTools::CopyAFile(templateFolder + "/Logo.png", logo, false);
- this->ConvertToWindowsSlash(logo);
+ ConvertToWindowsSlash(logo);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(logo) << "\" />\n";
this->AddedFiles.push_back(logo);
@@ -4408,7 +4458,7 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
std::string storeLogo = this->DefaultArtifactDir + "/StoreLogo.png";
cmSystemTools::CopyAFile(templateFolder + "/StoreLogo.png", storeLogo,
false);
- this->ConvertToWindowsSlash(storeLogo);
+ ConvertToWindowsSlash(storeLogo);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(storeLogo) << "\" />\n";
this->AddedFiles.push_back(storeLogo);
@@ -4416,14 +4466,14 @@ void cmVisualStudio10TargetGenerator::WriteCommonMissingFiles(
std::string splashScreen = this->DefaultArtifactDir + "/SplashScreen.png";
cmSystemTools::CopyAFile(templateFolder + "/SplashScreen.png", splashScreen,
false);
- this->ConvertToWindowsSlash(splashScreen);
+ ConvertToWindowsSlash(splashScreen);
this->WriteString("<Image Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(splashScreen) << "\" />\n";
this->AddedFiles.push_back(splashScreen);
// This file has already been added to the build so don't copy it
std::string keyFile = this->DefaultArtifactDir + "/Windows_TemporaryKey.pfx";
- this->ConvertToWindowsSlash(keyFile);
+ ConvertToWindowsSlash(keyFile);
this->WriteString("<None Include=\"", 2);
(*this->BuildFileStream) << cmVS10EscapeXML(keyFile) << "\" />\n";
}
@@ -4453,13 +4503,12 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceProperties(
{
if (this->ProjectType == csproj) {
const cmPropertyMap& props = sf->GetProperties();
- for (cmPropertyMap::const_iterator p = props.begin(); p != props.end();
- ++p) {
+ for (auto const& p : props) {
static const std::string propNamePrefix = "VS_CSHARP_";
- if (p->first.find(propNamePrefix) == 0) {
- std::string tagName = p->first.substr(propNamePrefix.length());
+ if (p.first.find(propNamePrefix) == 0) {
+ std::string tagName = p.first.substr(propNamePrefix.length());
if (!tagName.empty()) {
- const std::string val = props.GetPropertyValue(p->first);
+ const std::string val = props.GetPropertyValue(p.first);
if (!val.empty()) {
tags[tagName] = val;
} else {
@@ -4475,11 +4524,10 @@ void cmVisualStudio10TargetGenerator::WriteCSharpSourceProperties(
const std::map<std::string, std::string>& tags)
{
if (!tags.empty()) {
- for (std::map<std::string, std::string>::const_iterator i = tags.begin();
- i != tags.end(); ++i) {
+ for (const auto& i : tags) {
this->WriteString("<", 3);
- (*this->BuildFileStream) << i->first << ">" << cmVS10EscapeXML(i->second)
- << "</" << i->first << ">\n";
+ (*this->BuildFileStream) << i.first << ">" << cmVS10EscapeXML(i.second)
+ << "</" << i.first << ">\n";
}
}
}
@@ -4496,7 +4544,7 @@ void cmVisualStudio10TargetGenerator::GetCSharpSourceLink(
if (const char* l = sf->GetProperty("VS_CSHARP_Link")) {
link = l;
}
- this->ConvertToWindowsSlash(link);
+ ConvertToWindowsSlash(link);
}
}
}
@@ -4507,7 +4555,7 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
// Always search in the standard modules location.
std::string path = cmSystemTools::GetCMakeRoot() + "/";
path += relativeFilePath;
- this->ConvertToWindowsSlash(path);
+ ConvertToWindowsSlash(path);
return path;
}
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index fb24f1ac5..33d4fb775 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -7,6 +7,7 @@
#include <iosfwd>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
@@ -24,6 +25,8 @@ class cmVisualStudioGeneratorOptions;
class cmVisualStudio10TargetGenerator
{
+ CM_DISABLE_COPY(cmVisualStudio10TargetGenerator)
+
public:
cmVisualStudio10TargetGenerator(cmGeneratorTarget* target,
cmGlobalVisualStudio10Generator* gg);
@@ -51,7 +54,6 @@ private:
};
std::string ConvertPath(std::string const& path, bool forceRelative);
- static void ConvertToWindowsSlash(std::string& s);
void WriteString(const char* line, int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
@@ -90,18 +92,18 @@ private:
void WriteTargetSpecificReferences();
void WriteTargetsFileReferences();
+ std::vector<std::string> GetIncludes(std::string const& config,
+ std::string const& lang) const;
+
bool ComputeClOptions();
bool ComputeClOptions(std::string const& configName);
- void WriteClOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteClOptions(std::string const& config);
bool ComputeRcOptions();
bool ComputeRcOptions(std::string const& config);
- void WriteRCOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteRCOptions(std::string const& config);
bool ComputeCudaOptions();
bool ComputeCudaOptions(std::string const& config);
- void WriteCudaOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteCudaOptions(std::string const& config);
bool ComputeCudaLinkOptions();
bool ComputeCudaLinkOptions(std::string const& config);
@@ -109,20 +111,17 @@ private:
bool ComputeMasmOptions();
bool ComputeMasmOptions(std::string const& config);
- void WriteMasmOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteMasmOptions(std::string const& config);
bool ComputeNasmOptions();
bool ComputeNasmOptions(std::string const& config);
- void WriteNasmOptions(std::string const& config,
- std::vector<std::string> includes);
+ void WriteNasmOptions(std::string const& config);
bool ComputeLinkOptions();
bool ComputeLinkOptions(std::string const& config);
bool ComputeLibOptions();
bool ComputeLibOptions(std::string const& config);
void WriteLinkOptions(std::string const& config);
- void WriteMidlOptions(std::string const& config,
- std::vector<std::string> const& includes);
+ void WriteMidlOptions(std::string const& config);
void WriteAntBuildOptions(std::string const& config);
void OutputLinkIncremental(std::string const& configName);
void WriteCustomRule(cmSourceFile const* source,
@@ -172,7 +171,7 @@ private:
private:
typedef cmVisualStudioGeneratorOptions Options;
- typedef std::map<std::string, Options*> OptionsMap;
+ typedef std::map<std::string, std::unique_ptr<Options>> OptionsMap;
OptionsMap ClOptions;
OptionsMap RcOptions;
OptionsMap CudaOptions;
@@ -180,6 +179,7 @@ private:
OptionsMap MasmOptions;
OptionsMap NasmOptions;
OptionsMap LinkOptions;
+ std::string LangForClCompile;
std::string PathToProjectFile;
std::string ProjectFileExtension;
enum VsProjectType
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index b1686bec1..ccbff83e6 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -29,23 +29,8 @@ static std::string cmVisualStudioGeneratorOptionsEscapeForXML(std::string ret)
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
cmLocalVisualStudioGenerator* lg, Tool tool,
cmVisualStudio10TargetGenerator* g)
- : cmIDEOptions()
- , LocalGenerator(lg)
- , Version(lg->GetVersion())
- , CurrentTool(tool)
- , TargetGenerator(g)
+ : cmVisualStudioGeneratorOptions(lg, tool, nullptr, nullptr, g)
{
- // Preprocessor definitions are not allowed for linker tools.
- this->AllowDefine = (tool != Linker);
-
- // Slash options are allowed for VS.
- this->AllowSlash = true;
-
- this->FortranRuntimeDebug = false;
- this->FortranRuntimeDLL = false;
- this->FortranRuntimeMT = false;
-
- this->UnknownFlagField = "AdditionalOptions";
}
cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
@@ -64,6 +49,9 @@ cmVisualStudioGeneratorOptions::cmVisualStudioGeneratorOptions(
// Preprocessor definitions are not allowed for linker tools.
this->AllowDefine = (tool != Linker);
+ // include directories are not allowed for linker tools.
+ this->AllowInclude = (tool != Linker);
+
// Slash options are allowed for VS.
this->AllowSlash = true;
@@ -239,26 +227,38 @@ void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration()
// It translates to -arch=<virtual> -code=<real>.
cmSystemTools::ReplaceString(arch_name, "sm_", "compute_");
}
- for (std::vector<std::string>::iterator ci = codes.begin();
- ci != codes.end(); ++ci) {
- std::string entry = arch_name + "," + *ci;
+ for (auto const& c : codes) {
+ std::string entry = arch_name + "," + c;
result.push_back(entry);
}
}
- // Now add entries for the -gencode=<arch>,<code> pairs.
- for (std::vector<std::string>::iterator ei = gencode.begin();
- ei != gencode.end(); ++ei) {
- std::string entry = *ei;
+ // Now add entries for the following signatures:
+ // -gencode=<arch>,<code>
+ // -gencode=<arch>,[<code1>,<code2>]
+ // -gencode=<arch>,"<code1>,<code2>"
+ for (auto const& e : gencode) {
+ std::string entry = e;
cmSystemTools::ReplaceString(entry, "arch=", "");
cmSystemTools::ReplaceString(entry, "code=", "");
- result.push_back(entry);
+ cmSystemTools::ReplaceString(entry, "[", "");
+ cmSystemTools::ReplaceString(entry, "]", "");
+ cmSystemTools::ReplaceString(entry, "\"", "");
+
+ std::vector<std::string> codes = cmSystemTools::tokenize(entry, ",");
+ if (codes.size() >= 2) {
+ auto gencode_arch = cm::cbegin(codes);
+ for (auto ci = gencode_arch + 1; ci != cm::cend(codes); ++ci) {
+ std::string code_entry = *gencode_arch + "," + *ci;
+ result.push_back(code_entry);
+ }
+ }
}
}
void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
{
- static const char* ENABLE_UAC = "EnableUAC";
+ static std::string const ENABLE_UAC = "EnableUAC";
if (!HasFlag(ENABLE_UAC)) {
return;
}
@@ -304,8 +304,7 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
continue;
}
- AddFlag(uacMap[keyValue[0]].c_str(),
- uacExecuteLevelMap[keyValue[1]].c_str());
+ AddFlag(uacMap[keyValue[0]], uacExecuteLevelMap[keyValue[1]]);
continue;
}
@@ -314,11 +313,11 @@ void cmVisualStudioGeneratorOptions::FixManifestUACFlags()
// unknown uiAccess value
continue;
}
- AddFlag(uacMap[keyValue[0]].c_str(), keyValue[1].c_str());
+ AddFlag(uacMap[keyValue[0]], keyValue[1]);
continue;
}
- // unknwon sub option
+ // unknown sub option
}
AddFlag(ENABLE_UAC, "true");
@@ -500,6 +499,69 @@ void cmVisualStudioGeneratorOptions::OutputPreprocessorDefinitions(
}
}
+void cmVisualStudioGeneratorOptions::OutputAdditionalIncludeDirectories(
+ std::ostream& fout, const char* prefix, const char* suffix,
+ const std::string& lang)
+{
+ if (this->Includes.empty()) {
+ return;
+ }
+
+ const char* tag = "AdditionalIncludeDirectories";
+ if (lang == "CUDA") {
+ tag = "Include";
+ } else if (lang == "ASM_MASM" || lang == "ASM_NASM") {
+ tag = "IncludePaths";
+ }
+
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ // if there are configuration specific flags, then
+ // use the configuration specific tag for PreprocessorDefinitions
+ if (!this->Configuration.empty()) {
+ fout << prefix;
+ this->TargetGenerator->WritePlatformConfigTag(
+ tag, this->Configuration.c_str(), 0, 0, 0, &fout);
+ } else {
+ fout << prefix << "<" << tag << ">";
+ }
+ } else {
+ fout << prefix << tag << "=\"";
+ }
+
+ const char* sep = "";
+ for (std::string include : this->Includes) {
+ // first convert all of the slashes
+ std::string::size_type pos = 0;
+ while ((pos = include.find('/', pos)) != std::string::npos) {
+ include[pos] = '\\';
+ pos++;
+ }
+
+ if (lang == "ASM_NASM") {
+ include += "\\";
+ }
+
+ // Escape this include for the IDE.
+ fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
+ ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
+ : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ sep = ";";
+
+ if (lang == "Fortran") {
+ include += "/$(ConfigurationName)";
+ fout << sep << (this->Version >= cmGlobalVisualStudioGenerator::VS10
+ ? cmVisualStudio10GeneratorOptionsEscapeForXML(include)
+ : cmVisualStudioGeneratorOptionsEscapeForXML(include));
+ }
+ }
+
+ if (this->Version >= cmGlobalVisualStudioGenerator::VS10) {
+ fout << sep << "%(" << tag << ")</" << tag << ">" << suffix;
+ } else {
+ fout << "\"" << suffix;
+ }
+}
+
void cmVisualStudioGeneratorOptions::OutputFlagMap(std::ostream& fout,
const char* indent)
{
diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h
index 7c08a2c30..2dffe9b8c 100644
--- a/Source/cmVisualStudioGeneratorOptions.h
+++ b/Source/cmVisualStudioGeneratorOptions.h
@@ -86,6 +86,10 @@ public:
void OutputPreprocessorDefinitions(std::ostream& fout, const char* prefix,
const char* suffix,
const std::string& lang);
+ void OutputAdditionalIncludeDirectories(std::ostream& fout,
+ const char* prefix,
+ const char* suffix,
+ const std::string& lang);
void OutputFlagMap(std::ostream& fout, const char* indent);
void SetConfiguration(const char* config);
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index fc5fd2111..3464a1b30 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -33,7 +33,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
}
}
- if (!this->Makefile->CanIWriteThisFile(fileName.c_str())) {
+ if (!this->Makefile->CanIWriteThisFile(fileName)) {
std::string e =
"attempted to write a file: " + fileName + " into a source directory.";
this->SetError(e);
@@ -42,7 +42,7 @@ bool cmWriteFileCommand::InitialPass(std::vector<std::string> const& args,
}
std::string dir = cmSystemTools::GetFilenamePath(fileName);
- cmSystemTools::MakeDirectory(dir.c_str());
+ cmSystemTools::MakeDirectory(dir);
mode_t mode = 0;
diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx
index e54f1f356..1747c9c99 100644
--- a/Source/cmXCodeObject.cxx
+++ b/Source/cmXCodeObject.cxx
@@ -115,16 +115,15 @@ void cmXCodeObject::Print(std::ostream& out)
if (separator == "\n") {
out << separator;
}
- std::map<std::string, cmXCodeObject*>::iterator i;
cmXCodeObject::Indent(3 * indentFactor, out);
out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator;
- for (i = this->ObjectAttributes.begin(); i != this->ObjectAttributes.end();
- ++i) {
- if (i->first == "isa") {
+ for (const auto& keyVal : this->ObjectAttributes) {
+ if (keyVal.first == "isa") {
continue;
}
- PrintAttribute(out, 3, separator, indentFactor, i->first, i->second, this);
+ PrintAttribute(out, 3, separator, indentFactor, keyVal.first,
+ keyVal.second, this);
}
cmXCodeObject::Indent(2 * indentFactor, out);
out << "};\n";
@@ -167,11 +166,9 @@ void cmXCodeObject::PrintAttribute(std::ostream& out, int level,
if (separator == "\n") {
out << separator;
}
- std::map<std::string, cmXCodeObject*>::const_iterator i;
- for (i = object->ObjectAttributes.begin();
- i != object->ObjectAttributes.end(); ++i) {
- PrintAttribute(out, (level + 1) * factor, separator, factor, i->first,
- i->second, object);
+ for (const auto& keyVal : object->ObjectAttributes) {
+ PrintAttribute(out, (level + 1) * factor, separator, factor,
+ keyVal.first, keyVal.second, object);
}
cmXCodeObject::Indent(level * factor, out);
out << "};" << separator;
@@ -221,7 +218,7 @@ void cmXCodeObject::CopyAttributes(cmXCodeObject* copy)
this->Object = copy->Object;
}
-void cmXCodeObject::PrintString(std::ostream& os, std::string String)
+void cmXCodeObject::PrintString(std::ostream& os, const std::string& String)
{
// The string needs to be quoted if it contains any characters
// considered special by the Xcode project file parser.
@@ -234,13 +231,12 @@ void cmXCodeObject::PrintString(std::ostream& os, std::string String)
// Print the string, quoted and escaped as necessary.
os << quote;
- for (std::string::const_iterator i = String.begin(); i != String.end();
- ++i) {
- if (*i == '"' || *i == '\\') {
+ for (auto c : String) {
+ if (c == '"' || c == '\\') {
// Escape double-quotes and backslashes.
os << '\\';
}
- os << *i;
+ os << c;
}
os << quote;
}
diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h
index b0f1d31af..51e5d36d2 100644
--- a/Source/cmXCodeObject.h
+++ b/Source/cmXCodeObject.h
@@ -150,7 +150,7 @@ public:
return this->List;
}
void SetComment(const std::string& c) { this->Comment = c; }
- static void PrintString(std::ostream& os, std::string String);
+ static void PrintString(std::ostream& os, const std::string& String);
protected:
void PrintString(std::ostream& os) const;
diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h
index 981255d41..7bae21e2a 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 arbitrary 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/cm_codecvt.cxx b/Source/cm_codecvt.cxx
index cf55741a7..670585172 100644
--- a/Source/cm_codecvt.cxx
+++ b/Source/cm_codecvt.cxx
@@ -38,12 +38,14 @@ codecvt::codecvt(Encoding e)
}
}
-codecvt::~codecvt(){};
+codecvt::~codecvt()
+{
+}
bool codecvt::do_always_noconv() const throw()
{
return m_noconv;
-};
+}
std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
const char* from_end,
@@ -122,7 +124,7 @@ std::codecvt_base::result codecvt::do_out(mbstate_t& state, const char* from,
static_cast<void>(to_next);
return std::codecvt_base::noconv;
#endif
-};
+}
std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to,
char* to_end,
@@ -143,7 +145,7 @@ std::codecvt_base::result codecvt::do_unshift(mbstate_t& state, char* to,
static_cast<void>(to_end);
return std::codecvt_base::ok;
#endif
-};
+}
#if defined(_WIN32)
std::codecvt_base::result codecvt::Decode(mbstate_t& state, int size,
@@ -235,9 +237,9 @@ void codecvt::BufferPartial(mbstate_t& state, int size,
int codecvt::do_max_length() const throw()
{
return 4;
-};
+}
int codecvt::do_encoding() const throw()
{
return 0;
-};
+}
diff --git a/Source/cm_thread.hxx b/Source/cm_thread.hxx
new file mode 100644
index 000000000..84e6a5c32
--- /dev/null
+++ b/Source/cm_thread.hxx
@@ -0,0 +1,44 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+ file Copyright.txt or https://cmake.org/licensing for details. */
+#ifndef CM_THREAD_HXX
+#define CM_THREAD_HXX
+
+#include "cmConfigure.h" // IWYU pragma: keep
+#include "cm_uv.h"
+
+namespace cm {
+
+class shared_mutex
+{
+ uv_rwlock_t _M_;
+ CM_DISABLE_COPY(shared_mutex)
+
+public:
+ shared_mutex() { uv_rwlock_init(&_M_); }
+ ~shared_mutex() { uv_rwlock_destroy(&_M_); }
+
+ void lock() { uv_rwlock_wrlock(&_M_); }
+
+ void unlock() { uv_rwlock_wrunlock(&_M_); }
+
+ void lock_shared() { uv_rwlock_rdlock(&_M_); }
+
+ void unlock_shared() { uv_rwlock_rdunlock(&_M_); }
+};
+
+template <typename T>
+class shared_lock
+{
+ T& _mutex;
+ CM_DISABLE_COPY(shared_lock)
+
+public:
+ shared_lock(T& m)
+ : _mutex(m)
+ {
+ _mutex.lock_shared();
+ }
+ ~shared_lock() { _mutex.unlock_shared(); }
+};
+}
+#endif
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index fd7151f08..562072302 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -7,6 +7,7 @@
#include "cmDocumentation.h"
#include "cmDocumentationEntry.h"
#include "cmDocumentationFormatter.h"
+#include "cmDuration.h"
#include "cmExternalMakefileProjectGenerator.h"
#include "cmFileTimeComparison.h"
#include "cmGeneratorTarget.h"
@@ -34,14 +35,6 @@
#include <unordered_map>
#endif
-// only build kdevelop generator on non-windows platforms
-// when not bootstrapping cmake
-#if !defined(_WIN32)
-#if defined(CMAKE_BUILD_WITH_CMAKE)
-#define CMAKE_USE_KDEVELOP
-#endif
-#endif
-
#if defined(CMAKE_BUILD_WITH_CMAKE)
#define CMAKE_USE_ECLIPSE
#endif
@@ -87,10 +80,6 @@
#include "cmExtraKateGenerator.h"
#include "cmExtraSublimeTextGenerator.h"
-#ifdef CMAKE_USE_KDEVELOP
-#include "cmGlobalKdevelopGenerator.h"
-#endif
-
#ifdef CMAKE_USE_ECLIPSE
#include "cmExtraEclipseCDT4Generator.h"
#endif
@@ -110,6 +99,7 @@
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <iostream>
+#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
@@ -195,10 +185,16 @@ cmake::cmake(Role role)
this->SourceFileExtensions.push_back("cc");
this->SourceFileExtensions.push_back("cpp");
this->SourceFileExtensions.push_back("cxx");
+ this->SourceFileExtensions.push_back("cu");
this->SourceFileExtensions.push_back("m");
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++");
@@ -207,6 +203,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()
@@ -486,7 +487,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args,
if (this->GetWorkingMode() != NORMAL_MODE) {
std::string file(cmSystemTools::CollapseFullPath(path));
cmSystemTools::ConvertToUnixSlashes(file);
- mf.SetScriptModeFile(file.c_str());
+ mf.SetScriptModeFile(file);
mf.SetArgcArgv(args);
}
@@ -744,8 +745,13 @@ void cmake::SetArgs(const std::vector<std::string>& args,
}
cmGlobalGenerator* gen = this->CreateGlobalGenerator(value);
if (!gen) {
+ const char* kdevError = nullptr;
+ if (value.find("KDevelop3", 0) != std::string::npos) {
+ kdevError = "\nThe KDevelop3 generator is not supported anymore.";
+ }
+
cmSystemTools::Error("Could not create named generator ",
- value.c_str());
+ value.c_str(), kdevError);
this->PrintGeneratorList();
} else {
this->SetGlobalGenerator(gen);
@@ -777,10 +783,10 @@ void cmake::SetDirectoriesFromFile(const char* arg)
cacheFile += "/CMakeCache.txt";
std::string listFile = path;
listFile += "/CMakeLists.txt";
- if (cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (cmSystemTools::FileExists(cacheFile)) {
cachePath = path;
}
- if (cmSystemTools::FileExists(listFile.c_str())) {
+ if (cmSystemTools::FileExists(listFile)) {
listPath = path;
}
} else if (cmSystemTools::FileExists(arg)) {
@@ -863,7 +869,7 @@ int cmake::AddCMakePaths()
"Path to cpack program executable.", cmStateEnums::INTERNAL);
#endif
if (!cmSystemTools::FileExists(
- (cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake").c_str())) {
+ (cmSystemTools::GetCMakeRoot() + "/Modules/CMake.cmake"))) {
// couldn't find modules
cmSystemTools::Error(
"Could not find CMAKE_ROOT !!!\n"
@@ -890,9 +896,6 @@ void cmake::AddDefaultExtraGenerators()
this->ExtraGenerators.push_back(cmExtraEclipseCDT4Generator::GetFactory());
#endif
-#ifdef CMAKE_USE_KDEVELOP
- this->ExtraGenerators.push_back(cmGlobalKdevelopGenerator::GetFactory());
-#endif
#endif
}
@@ -910,7 +913,7 @@ void cmake::GetRegisteredGenerators(
info.name = name;
info.baseName = name;
info.isAlias = false;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
}
@@ -926,7 +929,7 @@ void cmake::GetRegisteredGenerators(
info.supportsPlatform = false;
info.supportsToolset = false;
info.isAlias = false;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
for (std::string const& a : eg->Aliases) {
GeneratorInfo info;
@@ -938,7 +941,7 @@ void cmake::GetRegisteredGenerators(
info.supportsPlatform = false;
info.supportsToolset = false;
info.isAlias = true;
- generators.push_back(info);
+ generators.push_back(std::move(info));
}
}
}
@@ -1000,7 +1003,7 @@ void cmake::SetHomeDirectory(const std::string& dir)
}
}
-const char* cmake::GetHomeDirectory() const
+std::string const& cmake::GetHomeDirectory() const
{
return this->State->GetSourceDirectory();
}
@@ -1013,7 +1016,7 @@ void cmake::SetHomeOutputDirectory(const std::string& dir)
}
}
-const char* cmake::GetHomeOutputDirectory() const
+std::string const& cmake::GetHomeOutputDirectory() const
{
return this->State->GetBinaryDirectory();
}
@@ -1024,11 +1027,11 @@ std::string cmake::FindCacheFile(const std::string& binaryDir)
cmSystemTools::ConvertToUnixSlashes(cachePath);
std::string cacheFile = cachePath;
cacheFile += "/CMakeCache.txt";
- if (!cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (!cmSystemTools::FileExists(cacheFile)) {
// search in parent directories for cache
std::string cmakeFiles = cachePath;
cmakeFiles += "/CMakeFiles";
- if (cmSystemTools::FileExists(cmakeFiles.c_str())) {
+ if (cmSystemTools::FileExists(cmakeFiles)) {
std::string cachePathFound =
cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
cachePath.c_str(), "/");
@@ -1084,7 +1087,7 @@ int cmake::DoPreConfigureChecks()
// Make sure the Source directory contains a CMakeLists.txt file.
std::string srcList = this->GetHomeDirectory();
srcList += "/CMakeLists.txt";
- if (!cmSystemTools::FileExists(srcList.c_str())) {
+ if (!cmSystemTools::FileExists(srcList)) {
std::ostringstream err;
if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) {
err << "The source directory \"" << this->GetHomeDirectory()
@@ -1165,7 +1168,7 @@ int cmake::HandleDeleteCacheVariables(const std::string& var)
save.help = help;
}
}
- saved.push_back(save);
+ saved.push_back(std::move(save));
}
// remove the cache
@@ -1269,7 +1272,7 @@ int cmake::ActualConfigure()
}
if (!res) {
this->AddCacheEntry(
- "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory(),
+ "CMAKE_HOME_DIRECTORY", this->GetHomeDirectory().c_str(),
"Source directory with the top level CMakeLists.txt file for this "
"project",
cmStateEnums::INTERNAL);
@@ -1326,6 +1329,25 @@ int cmake::ActualConfigure()
cmStateEnums::INTERNAL);
}
+ if (const char* instance =
+ this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
+ if (!this->GeneratorInstance.empty() &&
+ this->GeneratorInstance != instance) {
+ std::string message = "Error: generator instance: ";
+ message += this->GeneratorInstance;
+ message += "\nDoes not match the instance used previously: ";
+ message += instance;
+ message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
+ "directory or choose a different binary directory.";
+ cmSystemTools::Error(message.c_str());
+ return -2;
+ }
+ } else {
+ this->AddCacheEntry(
+ "CMAKE_GENERATOR_INSTANCE", this->GeneratorInstance.c_str(),
+ "Generator instance identifier.", cmStateEnums::INTERNAL);
+ }
+
if (const char* platformName =
this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
if (!this->GeneratorPlatform.empty() &&
@@ -1453,12 +1475,12 @@ void cmake::CreateDefaultGlobalGenerator()
if (vsSetupAPIHelper.IsVS2017Installed()) {
found = "Visual Studio 15 2017";
} else {
- for (VSVersionedGenerator const* g = cmArrayBegin(vsGenerators);
- found.empty() && g != cmArrayEnd(vsGenerators); ++g) {
- for (const char* const* v = cmArrayBegin(vsVariants);
- found.empty() && v != cmArrayEnd(vsVariants); ++v) {
- for (const char* const* e = cmArrayBegin(vsEntries);
- found.empty() && e != cmArrayEnd(vsEntries); ++e) {
+ for (VSVersionedGenerator const* g = cm::cbegin(vsGenerators);
+ found.empty() && g != cm::cend(vsGenerators); ++g) {
+ for (const char* const* v = cm::cbegin(vsVariants);
+ found.empty() && v != cm::cend(vsVariants); ++v) {
+ for (const char* const* e = cm::cbegin(vsEntries);
+ found.empty() && e != cm::cend(vsEntries); ++e) {
std::string const reg = vsregBase + *v + g->MSVersion + *e;
std::string dir;
if (cmSystemTools::ReadRegistryValue(reg, dir,
@@ -1487,14 +1509,14 @@ void cmake::PreLoadCMakeFiles()
std::string pre_load = this->GetHomeDirectory();
if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if (cmSystemTools::FileExists(pre_load.c_str())) {
+ if (cmSystemTools::FileExists(pre_load)) {
this->ReadListFile(args, pre_load.c_str());
}
}
pre_load = this->GetHomeOutputDirectory();
if (!pre_load.empty()) {
pre_load += "/PreLoad.cmake";
- if (cmSystemTools::FileExists(pre_load.c_str())) {
+ if (cmSystemTools::FileExists(pre_load)) {
this->ReadListFile(args, pre_load.c_str());
}
}
@@ -1627,6 +1649,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);
@@ -1687,7 +1724,7 @@ int cmake::LoadCache()
// if it does exist, but isn't readable then warn the user
std::string cacheFile = this->GetHomeOutputDirectory();
cacheFile += "/CMakeCache.txt";
- if (cmSystemTools::FileExists(cacheFile.c_str())) {
+ if (cmSystemTools::FileExists(cacheFile)) {
cmSystemTools::Error(
"There is a CMakeCache.txt file for the current binary tree but "
"cmake does not have permission to read it. Please check the "
@@ -1716,8 +1753,8 @@ bool cmake::LoadCache(const std::string& path, bool internal,
bool result = this->State->LoadCache(path, internal, excludes, includes);
static const char* entries[] = { "CMAKE_CACHE_MAJOR_VERSION",
"CMAKE_CACHE_MINOR_VERSION" };
- for (const char* const* nameIt = cmArrayBegin(entries);
- nameIt != cmArrayEnd(entries); ++nameIt) {
+ for (const char* const* nameIt = cm::cbegin(entries);
+ nameIt != cm::cend(entries); ++nameIt) {
this->UnwatchUnusedCli(*nameIt);
}
return result;
@@ -1725,13 +1762,13 @@ bool cmake::LoadCache(const std::string& path, bool internal,
bool cmake::SaveCache(const std::string& path)
{
- bool result = this->State->SaveCache(path);
+ bool result = this->State->SaveCache(path, this->GetMessenger());
static const char* entries[] = { "CMAKE_CACHE_MAJOR_VERSION",
"CMAKE_CACHE_MINOR_VERSION",
"CMAKE_CACHE_PATCH_VERSION",
"CMAKE_CACHEFILE_DIR" };
- for (const char* const* nameIt = cmArrayBegin(entries);
- nameIt != cmArrayEnd(entries); ++nameIt) {
+ for (const char* const* nameIt = cm::cbegin(entries);
+ nameIt != cm::cend(entries); ++nameIt) {
this->UnwatchUnusedCli(*nameIt);
}
return result;
@@ -1771,7 +1808,7 @@ void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
for (cmGlobalGeneratorFactory* g : this->Generators) {
cmDocumentationEntry e;
g->GetDocumentation(e);
- v.push_back(e);
+ v.push_back(std::move(e));
}
for (cmExternalMakefileProjectGeneratorFactory* eg : this->ExtraGenerators) {
const std::string doc = eg->GetDocumentation();
@@ -1782,7 +1819,7 @@ void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
cmDocumentationEntry e;
e.Name = a;
e.Brief = doc;
- v.push_back(e);
+ v.push_back(std::move(e));
}
// Full names:
@@ -1793,7 +1830,7 @@ void cmake::GetGeneratorDocumentation(std::vector<cmDocumentationEntry>& v)
e.Name =
cmExternalMakefileProjectGenerator::CreateFullGeneratorName(g, name);
e.Brief = doc;
- v.push_back(e);
+ v.push_back(std::move(e));
}
}
}
@@ -1854,7 +1891,7 @@ int cmake::CheckBuildSystem()
}
// If the file provided does not exist, we have to rerun.
- if (!cmSystemTools::FileExists(this->CheckBuildSystemArgument.c_str())) {
+ if (!cmSystemTools::FileExists(this->CheckBuildSystemArgument)) {
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake missing file: " << this->CheckBuildSystemArgument
@@ -1908,8 +1945,7 @@ int cmake::CheckBuildSystem()
cmSystemTools::ExpandListArgument(productStr, products);
}
for (std::string const& p : products) {
- if (!(cmSystemTools::FileExists(p.c_str()) ||
- cmSystemTools::FileIsSymlink(p))) {
+ if (!(cmSystemTools::FileExists(p) || cmSystemTools::FileIsSymlink(p))) {
if (verbose) {
std::ostringstream msg;
msg << "Re-run cmake, missing byproduct: " << p << "\n";
@@ -2107,7 +2143,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
std::string destPath = cwd + "/__cmake_systeminformation";
cmSystemTools::RemoveADirectory(destPath);
- if (!cmSystemTools::MakeDirectory(destPath.c_str())) {
+ if (!cmSystemTools::MakeDirectory(destPath)) {
std::cerr << "Error: --system-information must be run from a "
"writable directory!\n";
return 1;
@@ -2139,7 +2175,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
}
// no option assume it is the output file
else {
- if (!cmSystemTools::FileIsFullPath(arg.c_str())) {
+ if (!cmSystemTools::FileIsFullPath(arg)) {
resultFile = cwd;
resultFile += "/";
}
@@ -2176,9 +2212,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
std::vector<std::string> args2;
args2.push_back(args[0]);
args2.push_back(destPath);
- std::string resultArg = "-DRESULT_FILE=";
- resultArg += resultFile;
- args2.push_back(resultArg);
+ args2.push_back("-DRESULT_FILE=" + resultFile);
int res = this->Run(args2, false);
if (res != 0) {
@@ -2360,6 +2394,14 @@ int cmake::Build(const std::string& dir, const std::string& target,
<< "\"\n";
return 1;
}
+ const char* cachedGeneratorInstance =
+ this->State->GetCacheEntryValue("CMAKE_GENERATOR_INSTANCE");
+ if (cachedGeneratorInstance) {
+ cmMakefile mf(gen.get(), this->GetCurrentSnapshot());
+ if (!gen->SetGeneratorInstance(cachedGeneratorInstance, &mf)) {
+ return 1;
+ }
+ }
std::string output;
std::string projName;
const char* cachedProjectName =
@@ -2386,7 +2428,7 @@ int cmake::Build(const std::string& dir, const std::string& target,
cmGlobalVisualStudio8Generator::GetGenerateStampList();
// Note that the stampList file only exists for VS generators.
- if (cmSystemTools::FileExists(stampList.c_str()) &&
+ if (cmSystemTools::FileExists(stampList) &&
!cmakeCheckStampList(stampList.c_str(), false)) {
// Correctly initialize the home (=source) and home output (=binary)
@@ -2421,8 +2463,51 @@ int cmake::Build(const std::string& dir, const std::string& target,
#endif
return gen->Build("", dir, projName, target, output, "", config, clean,
- false, verbose, 0, cmSystemTools::OUTPUT_PASSTHROUGH,
- nativeOptions);
+ false, verbose, cmDuration::zero(),
+ cmSystemTools::OUTPUT_PASSTHROUGH, nativeOptions);
+}
+
+bool cmake::Open(const std::string& dir, bool dryRun)
+{
+ this->SetHomeDirectory("");
+ this->SetHomeOutputDirectory("");
+ if (!cmSystemTools::FileIsDirectory(dir)) {
+ std::cerr << "Error: " << dir << " is not a directory\n";
+ return false;
+ }
+
+ std::string cachePath = FindCacheFile(dir);
+ if (!this->LoadCache(cachePath)) {
+ std::cerr << "Error: could not load cache\n";
+ return false;
+ }
+ const char* genName = this->State->GetCacheEntryValue("CMAKE_GENERATOR");
+ if (!genName) {
+ std::cerr << "Error: could not find CMAKE_GENERATOR in Cache\n";
+ return false;
+ }
+ const char* extraGenName =
+ this->State->GetInitializedCacheValue("CMAKE_EXTRA_GENERATOR");
+ std::string fullName =
+ cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
+ genName, extraGenName ? extraGenName : "");
+
+ std::unique_ptr<cmGlobalGenerator> gen(
+ this->CreateGlobalGenerator(fullName));
+ if (!gen.get()) {
+ std::cerr << "Error: could create CMAKE_GENERATOR \"" << fullName
+ << "\"\n";
+ return false;
+ }
+
+ const char* cachedProjectName =
+ this->State->GetCacheEntryValue("CMAKE_PROJECT_NAME");
+ if (!cachedProjectName) {
+ std::cerr << "Error: could not find CMAKE_PROJECT_NAME in Cache\n";
+ return false;
+ }
+
+ return gen->Open(dir, cachedProjectName, dryRun);
}
void cmake::WatchUnusedCli(const std::string& var)
diff --git a/Source/cmake.h b/Source/cmake.h
index b31b6f5ce..1ac549b90 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"
@@ -141,9 +142,9 @@ public:
* path-to-source cmake was run with.
*/
void SetHomeDirectory(const std::string& dir);
- const char* GetHomeDirectory() const;
+ std::string const& GetHomeDirectory() const;
void SetHomeOutputDirectory(const std::string& dir);
- const char* GetHomeOutputDirectory() const;
+ std::string const& GetHomeOutputDirectory() const;
//@}
/**
@@ -203,6 +204,12 @@ public:
///! Get the names of the current registered generators
void GetRegisteredGenerators(std::vector<GeneratorInfo>& generators) const;
+ ///! Set the name of the selected generator-specific instance.
+ void SetGeneratorInstance(std::string const& instance)
+ {
+ this->GeneratorInstance = instance;
+ }
+
///! Set the name of the selected generator-specific platform.
void SetGeneratorPlatform(std::string const& ts)
{
@@ -219,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).
*/
@@ -401,6 +424,9 @@ public:
const std::string& config,
const std::vector<std::string>& nativeOptions, bool clean);
+ ///! run the --open option
+ bool Open(const std::string& dir, bool dryRun);
+
void UnwatchUnusedCli(const std::string& var);
void WatchUnusedCli(const std::string& var);
@@ -428,6 +454,7 @@ protected:
cmGlobalGenerator* GlobalGenerator;
std::map<std::string, DiagLevel> DiagLevels;
+ std::string GeneratorInstance;
std::string GeneratorPlatform;
std::string GeneratorToolset;
@@ -476,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/cmakemain.cxx b/Source/cmakemain.cxx
index a1dfc3e89..b185a1bc4 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -16,10 +16,6 @@
#include "cmDynamicLoader.h"
#endif
-#ifdef _WIN32
-#include <fcntl.h> /* _O_TEXT */
-#include <stdlib.h> /* _set_fmode, _fmode */
-#endif
#include "cm_uv.h"
#include "cmsys/Encoding.hxx"
@@ -66,6 +62,7 @@ static const char* cmDocumentationOptions[][2] = {
{ "-E", "CMake command mode." },
{ "-L[A][H]", "List non-advanced cached variables." },
{ "--build <dir>", "Build a CMake-generated project binary tree." },
+ { "--open <dir>", "Open generated project in the associated application." },
{ "-N", "View mode only." },
{ "-P <file>", "Process script mode." },
{ "--find-package", "Run in pkg-config like mode." },
@@ -100,6 +97,7 @@ static int do_command(int ac, char const* const* av)
int do_cmake(int ac, char const* const* av);
static int do_build(int ac, char const* const* av);
+static int do_open(int ac, char const* const* av);
static cmMakefile* cmakemainGetMakefile(void* clientdata)
{
@@ -168,24 +166,16 @@ int main(int ac, char const* const* av)
ac = args.argc();
av = args.argv();
-#if defined(_WIN32)
- // Perform libuv one-time initialization now, and then un-do its
- // global _fmode setting so that using libuv does not change the
- // default file text/binary mode. See libuv issue 840.
- uv_loop_close(uv_default_loop());
-#ifdef _MSC_VER
- _set_fmode(_O_TEXT);
-#else
- _fmode = _O_TEXT;
-#endif
-#endif
-
cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(av[0]);
if (ac > 1) {
if (strcmp(av[1], "--build") == 0) {
return do_build(ac, av);
}
+ if (strcmp(av[1], "--open") == 0) {
+ return do_open(ac, av);
+ }
if (strcmp(av[1], "-E") == 0) {
return do_command(ac, av);
}
@@ -423,3 +413,41 @@ static int do_build(int ac, char const* const* av)
return cm.Build(dir, target, config, nativeOptions, clean);
#endif
}
+
+static int do_open(int ac, char const* const* av)
+{
+#ifndef CMAKE_BUILD_WITH_CMAKE
+ std::cerr << "This cmake does not support --open\n";
+ return -1;
+#else
+ std::string dir;
+
+ enum Doing
+ {
+ DoingNone,
+ DoingDir,
+ };
+ Doing doing = DoingDir;
+ for (int i = 2; i < ac; ++i) {
+ switch (doing) {
+ case DoingDir:
+ dir = cmSystemTools::CollapseFullPath(av[i]);
+ doing = DoingNone;
+ break;
+ default:
+ std::cerr << "Unknown argument " << av[i] << std::endl;
+ dir.clear();
+ break;
+ }
+ }
+ if (dir.empty()) {
+ std::cerr << "Usage: cmake --open <dir>\n";
+ return 1;
+ }
+
+ cmake cm(cmake::RoleInternal);
+ cmSystemTools::SetMessageCallback(cmakemainMessageCallback, &cm);
+ cm.SetProgressCallback(cmakemainProgressCallback, &cm);
+ return cm.Open(dir, false) ? 0 : 1;
+#endif
+}
diff --git a/Source/cmakexbuild.cxx b/Source/cmakexbuild.cxx
index 20ead4785..295194595 100644
--- a/Source/cmakexbuild.cxx
+++ b/Source/cmakexbuild.cxx
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "cmDuration.h"
#include "cmSystemTools.h"
// This is a wrapper program for xcodebuild
@@ -27,7 +28,8 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
std::vector<char> out;
std::vector<char> err;
std::string line;
- int pipe = cmSystemTools::WaitForLine(cp, line, 100.0, out, err);
+ int pipe =
+ cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out, err);
while (pipe != cmsysProcess_Pipe_None) {
if (line.find("/bin/sh: bad interpreter: Text file busy") !=
std::string::npos) {
@@ -45,7 +47,8 @@ int RunXCode(std::vector<const char*>& argv, bool& hitbug)
std::cout << line << "\n";
}
}
- pipe = cmSystemTools::WaitForLine(cp, line, 100, out, err);
+ pipe = cmSystemTools::WaitForLine(cp, line, std::chrono::seconds(100), out,
+ err);
}
cmsysProcess_WaitForExit(cp, nullptr);
if (cmsysProcess_GetState(cp) == cmsysProcess_State_Exited) {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 69339b448..0988c3c04 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -3,10 +3,12 @@
#include "cmcmd.h"
#include "cmAlgorithms.h"
+#include "cmDuration.h"
#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"
@@ -34,6 +36,7 @@
#include "cmsys/Terminal.h"
#include <algorithm>
#include <iostream>
+#include <iterator>
#include <memory> // IWYU pragma: keep
#include <sstream>
#include <stdio.h>
@@ -101,7 +104,7 @@ void CMakeCommandUsage(const char* program)
<< " sleep <number>... - sleep for given number of seconds\n"
<< " tar [cxt][vf][zjJ] file.tar [file/dir1 file/dir2 ...]\n"
<< " - create or extract a tar or zip archive\n"
- << " time command [args...] - run command and return elapsed time\n"
+ << " time command [args...] - run command and display elapsed time\n"
<< " touch file - touch a file.\n"
<< " touch_nocreate file - touch a file but do not create it.\n"
#if defined(_WIN32) && !defined(__CYGWIN__)
@@ -268,10 +271,12 @@ static int HandleCppLint(const std::string& runCmd,
<< "\n";
return 1;
}
-
+ std::cerr << "Warning: cpplint diagnostics:\n";
// Output the output from cpplint to stderr
std::cerr << stdOut;
- return ret;
+ // always return 0 so the build can continue as cpplint returns non-zero
+ // for any warning
+ return 0;
}
static int HandleCppCheck(const std::string& runCmd,
@@ -371,8 +376,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
doing_options = false;
} else if (doing_options) {
bool optionFound = false;
- for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
- cc != cmArrayEnd(CoCompilers); ++cc) {
+ for (CoCompiler const* cc = cm::cbegin(CoCompilers);
+ cc != cm::cend(CoCompilers); ++cc) {
size_t optionLen = strlen(cc->Option);
if (arg.compare(0, optionLen, cc->Option) == 0) {
optionFound = true;
@@ -402,8 +407,8 @@ int cmcmd::HandleCoCompileCommands(std::vector<std::string>& args)
if (jobs.empty()) {
std::cerr << "__run_co_compile missing command to run. "
"Looking for one or more of the following:\n";
- for (CoCompiler const* cc = cmArrayBegin(CoCompilers);
- cc != cmArrayEnd(CoCompilers); ++cc) {
+ for (CoCompiler const* cc = cm::cbegin(CoCompilers);
+ cc != cm::cend(CoCompilers); ++cc) {
std::cerr << cc->Option << "\n";
}
return 1;
@@ -636,7 +641,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// If error occurs we want to continue copying next files.
bool return_value = false;
for (std::string::size_type cc = 2; cc < args.size(); cc++) {
- if (!cmSystemTools::MakeDirectory(args[cc].c_str())) {
+ if (!cmSystemTools::MakeDirectory(args[cc])) {
std::cerr << "Error creating directory \"" << args[cc] << "\".\n";
return_value = true;
}
@@ -663,7 +668,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Complain if the file could not be removed, still exists,
// and the -f option was not given.
if (!cmSystemTools::RemoveFile(args[cc]) && !force &&
- cmSystemTools::FileExists(args[cc].c_str())) {
+ cmSystemTools::FileExists(args[cc])) {
return 1;
}
}
@@ -784,7 +789,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
// Command to change directory and run a program.
if (args[1] == "chdir" && args.size() >= 4) {
std::string const& directory = args[2];
- if (!cmSystemTools::FileExists(directory.c_str())) {
+ if (!cmSystemTools::FileExists(directory)) {
cmSystemTools::Error("Directory does not exist for chdir command: ",
args[2].c_str());
return 1;
@@ -793,10 +798,9 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
std::string command =
cmWrap('"', cmMakeRange(args).advance(3), '"', " ");
int retval = 0;
- int timeout = 0;
if (cmSystemTools::RunSingleCommand(
command.c_str(), nullptr, nullptr, &retval, directory.c_str(),
- cmSystemTools::OUTPUT_PASSTHROUGH, timeout)) {
+ cmSystemTools::OUTPUT_PASSTHROUGH, cmDuration::zero())) {
return retval;
}
@@ -822,7 +826,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
count = atoi(args[3].c_str());
}
if (count) {
- cmSystemTools::MakeDirectory(dirName.c_str());
+ cmSystemTools::MakeDirectory(dirName);
// write the count into the directory
std::string fName = dirName;
fName += "/count.txt";
@@ -991,11 +995,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
@@ -1024,8 +1037,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args)
} else if (cmHasLiteralPrefix(arg, "--format=")) {
format = arg.substr(9);
bool isKnown =
- std::find(cmArrayBegin(knownFormats), cmArrayEnd(knownFormats),
- format) != cmArrayEnd(knownFormats);
+ std::find(cm::cbegin(knownFormats), cm::cend(knownFormats),
+ format) != cm::cend(knownFormats);
if (!isKnown) {
cmSystemTools::Error("Unknown -E tar --format= argument: ",
@@ -1224,9 +1237,12 @@ int cmcmd::HashSumFile(std::vector<std::string>& args, cmCryptoHash::Algo algo)
int cmcmd::SymlinkLibrary(std::vector<std::string>& args)
{
int result = 0;
- std::string const& realName = args[2];
- std::string const& soName = args[3];
- std::string const& name = args[4];
+ std::string realName = args[2];
+ std::string soName = args[3];
+ std::string name = args[4];
+ cmSystemTools::ConvertToUnixSlashes(realName);
+ cmSystemTools::ConvertToUnixSlashes(soName);
+ cmSystemTools::ConvertToUnixSlashes(name);
if (soName != realName) {
if (!cmcmd::SymlinkInternal(realName, soName)) {
cmSystemTools::ReportLastSystemError("cmake_symlink_library");
@@ -1258,8 +1274,7 @@ int cmcmd::SymlinkExecutable(std::vector<std::string>& args)
bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
{
- if (cmSystemTools::FileExists(link.c_str()) ||
- cmSystemTools::FileIsSymlink(link)) {
+ if (cmSystemTools::FileExists(link) || cmSystemTools::FileIsSymlink(link)) {
cmSystemTools::RemoveFile(link);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
diff --git a/Source/ctest.cxx b/Source/ctest.cxx
index f6466fad7..0a6d1d25d 100644
--- a/Source/ctest.cxx
+++ b/Source/ctest.cxx
@@ -104,8 +104,6 @@ static const char* cmDocumentationOptions[][2] = {
{ "--test-timeout", "The time limit in seconds, internal use only." },
{ "--test-load", "CPU load threshold for starting new parallel tests." },
{ "--tomorrow-tag", "Nightly or experimental starts with next day tag." },
- { "--ctest-config", "The configuration file used to initialize CTest state "
- "when submitting dashboards." },
{ "--overwrite", "Overwrite CTest configuration option." },
{ "--extra-submit <file>[;<file>]", "Submit extra files to the dashboard." },
{ "--force-new-ctest-process",
@@ -139,6 +137,7 @@ int main(int argc, char const* const* argv)
cmSystemTools::DoNotInheritStdPipes();
cmSystemTools::EnableMSVCDebugHook();
+ cmSystemTools::InitializeLibUV();
cmSystemTools::FindCMakeResources(argv[0]);
// Dispatch 'ctest --launch' mode directly.
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 21568bbed..4fc176b37 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -83,7 +83,9 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR)
FOREACH(p
+ CMP0022 # CMake 2.8, Define link interface - required by android_mk export
CMP0025 # CMake 3.0, Compiler id for Apple Clang is now AppleClang.
+ CMP0042 # CMake 3.0, MACOSX_RPATH is enabled by default.
CMP0048 # CMake 3.0, Let the project command manage version variables.
CMP0056 # CMake 3.2, Honor link flags in try_compile() source-file signature.
CMP0063 # CMake 3.3, Honor visibility properties for all target types.
@@ -445,8 +447,13 @@ KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_PTRDIFF_T
"Checking whether C compiler has ptrdiff_t in stddef.h" DIRECT)
KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_SSIZE_T
"Checking whether C compiler has ssize_t in unistd.h" DIRECT)
+IF(KWSYS_USE_Process)
+ KWSYS_PLATFORM_C_TEST(KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+ "Checking whether C compiler has clock_gettime" DIRECT)
+ENDIF()
+
SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES
- COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}"
+ COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T} -DKWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC=${KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC}"
)
IF(DEFINED KWSYS_PROCESS_USE_SELECT)
@@ -489,6 +496,24 @@ IF(KWSYS_USE_SystemTools)
KWSYS_CXX_STAT_HAS_ST_MTIM=${KWSYS_CXX_STAT_HAS_ST_MTIM}
KWSYS_CXX_STAT_HAS_ST_MTIMESPEC=${KWSYS_CXX_STAT_HAS_ST_MTIMESPEC}
)
+ IF(NOT WIN32)
+ IF(KWSYS_STANDALONE)
+ OPTION(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES "If true, Windows paths will be supported on Unix as well" ON)
+ ENDIF()
+ IF(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
+ SET_PROPERTY(SOURCE SystemTools.cxx testSystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES
+ )
+ ENDIF()
+ ENDIF()
+
+ # Disable getpwnam for static linux builds since it depends on shared glibc
+ GET_PROPERTY(SHARED_LIBS_SUPPORTED GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS)
+ IF(CMAKE_SYSTEM_NAME MATCHES "Linux" AND NOT SHARED_LIBS_SUPPORTED)
+ SET_PROPERTY(SOURCE SystemTools.cxx APPEND PROPERTY COMPILE_DEFINITIONS
+ HAVE_GETPWNAM=0
+ )
+ ENDIF()
ENDIF()
IF(KWSYS_USE_SystemInformation)
@@ -571,7 +596,7 @@ IF(KWSYS_USE_SystemInformation)
CHECK_INCLUDE_FILE_CXX("execinfo.h" KWSYS_CXX_HAS_EXECINFOH)
IF (KWSYS_CXX_HAS_EXECINFOH)
# we have the backtrace header check if it
- # can be used with this compiler
+ # can be used with this compiler
SET(KWSYS_PLATFORM_CXX_TEST_LINK_LIBRARIES ${EXECINFO_LIB})
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BACKTRACE
"Checking whether backtrace works with this C++ compiler" DIRECT)
@@ -700,9 +725,13 @@ ENDIF()
# selected components. Initialize with required components.
SET(KWSYS_CLASSES)
SET(KWSYS_H_FILES Configure SharedForward)
-SET(KWSYS_HXX_FILES Configure String
- hashtable hash_fun hash_map hash_set
- )
+SET(KWSYS_HXX_FILES Configure String)
+
+IF(NOT CMake_SOURCE_DIR)
+ SET(KWSYS_HXX_FILES ${KWSYS_HXX_FILES}
+ hashtable hash_fun hash_map hash_set
+ )
+ENDIF()
# Add selected C++ classes.
SET(cppclasses
@@ -893,7 +922,7 @@ IF(KWSYS_C_SRCS OR KWSYS_CXX_SRCS)
# Set up include usage requirement
IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
- $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
IF(KWSYS_INSTALL_INCLUDE_DIR)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_INTERFACE} INTERFACE
$<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
@@ -947,7 +976,7 @@ IF(KWSYS_ENABLE_C AND KWSYS_C_SRCS)
# Set up include usage requirement
IF(COMMAND TARGET_INCLUDE_DIRECTORIES)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
- $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
+ $<BUILD_INTERFACE:${KWSYS_HEADER_ROOT}>)
IF(KWSYS_INSTALL_INCLUDE_DIR)
TARGET_INCLUDE_DIRECTORIES(${KWSYS_TARGET_C_INTERFACE} INTERFACE
$<INSTALL_INTERFACE:${KWSYS_INSTALL_INCLUDE_DIR}>)
@@ -1003,11 +1032,11 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# C tests
SET(KWSYS_C_TESTS
- testEncode
- testTerminal
+ testEncode.c
+ testTerminal.c
)
IF(KWSYS_STANDALONE)
- SET(KWSYS_C_TESTS ${KWSYS_C_TESTS} testFail)
+ SET(KWSYS_C_TESTS ${KWSYS_C_TESTS} testFail.c)
ENDIF()
CREATE_TEST_SOURCELIST(
KWSYS_C_TEST_SRCS ${KWSYS_NAMESPACE}TestsC.c
@@ -1016,31 +1045,33 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
ADD_EXECUTABLE(${KWSYS_NAMESPACE}TestsC ${KWSYS_C_TEST_SRCS})
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestsC PROPERTY LABELS ${KWSYS_LABELS_EXE})
TARGET_LINK_LIBRARIES(${KWSYS_NAMESPACE}TestsC ${KWSYS_TARGET_C_LINK})
- FOREACH(test ${KWSYS_C_TESTS})
+ FOREACH(testfile ${KWSYS_C_TESTS})
+ get_filename_component(test "${testfile}" NAME_WE)
ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsC ${test} ${KWSYS_TEST_ARGS_${test}})
SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST})
ENDFOREACH()
# C++ tests
- IF(NOT WATCOM)
+ IF(NOT WATCOM AND NOT CMake_SOURCE_DIR)
SET(KWSYS_CXX_TESTS
- testHashSTL
+ testHashSTL.cxx
)
ENDIF()
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
- testSystemTools
- testCommandLineArguments
- testCommandLineArguments1
- testDirectory
+ testConfigure.cxx
+ testSystemTools.cxx
+ testCommandLineArguments.cxx
+ testCommandLineArguments1.cxx
+ testDirectory.cxx
)
IF(KWSYS_STL_HAS_WSTRING)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
- testEncoding
+ testEncoding.cxx
)
ENDIF()
IF(KWSYS_USE_FStream)
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
- testFStream
+ testFStream.cxx
)
ENDIF()
IF(KWSYS_USE_ConsoleBuf)
@@ -1052,7 +1083,7 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET_PROPERTY(TARGET testConsoleBufChild PROPERTY LABELS ${KWSYS_LABELS_EXE})
TARGET_LINK_LIBRARIES(testConsoleBufChild ${KWSYS_TARGET_LINK})
SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
- testConsoleBuf
+ testConsoleBuf.cxx
)
IF("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" AND
CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "19.0.23506")
@@ -1062,10 +1093,10 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE})
ENDIF()
IF(KWSYS_USE_SystemInformation)
- SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation)
+ SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testSystemInformation.cxx)
ENDIF()
IF(KWSYS_USE_DynamicLoader)
- SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader)
+ SET(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS} testDynamicLoader.cxx)
# If kwsys contains the DynamicLoader, need extra library
ADD_LIBRARY(${KWSYS_NAMESPACE}TestDynload MODULE testDynload.c)
SET_PROPERTY(TARGET ${KWSYS_NAMESPACE}TestDynload PROPERTY LABELS ${KWSYS_LABELS_LIB})
@@ -1124,7 +1155,8 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
-p
some junk at the end
)
- FOREACH(test ${KWSYS_CXX_TESTS})
+ FOREACH(testfile ${KWSYS_CXX_TESTS})
+ get_filename_component(test "${testfile}" NAME_WE)
ADD_TEST(kwsys.${test} ${EXEC_DIR}/${KWSYS_NAMESPACE}TestsCxx ${test} ${KWSYS_TEST_ARGS_${test}})
SET_PROPERTY(TEST kwsys.${test} PROPERTY LABELS ${KWSYS_LABELS_TEST})
ENDFOREACH()
@@ -1142,17 +1174,22 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET_TESTS_PROPERTIES(kwsys.testProcess-${n} PROPERTIES TIMEOUT 120)
ENDFOREACH()
+ SET(testProcess_COMPILE_FLAGS "")
# Some Apple compilers produce bad optimizations in this source.
IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$")
- SET_SOURCE_FILES_PROPERTIES(testProcess.c PROPERTIES COMPILE_FLAGS -O0)
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0")
ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND
NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND
NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1"))
# Tell IBM XL not to warn about our test infinite loop
# v13.1.1 and newer on Linux ppc64le is clang based and does not accept
# the -qsuppress option
- SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS -qsuppress=1500-010)
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010")
+ ENDIF()
+ IF(CMAKE_C_FLAGS MATCHES "-fsanitize=")
+ SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT")
ENDIF()
+ SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}")
# Test SharedForward
CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/testSharedForward.c.in
diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx
index 5613bd7ab..a6387eaba 100644
--- a/Source/kwsys/CommandLineArguments.cxx
+++ b/Source/kwsys/CommandLineArguments.cxx
@@ -68,8 +68,8 @@ class CommandLineArgumentsInternal
public:
CommandLineArgumentsInternal()
{
- this->UnknownArgumentCallback = 0;
- this->ClientData = 0;
+ this->UnknownArgumentCallback = KWSYS_NULLPTR;
+ this->ClientData = KWSYS_NULLPTR;
this->LastArgument = 0;
}
@@ -187,7 +187,7 @@ int CommandLineArguments::Parse()
switch (cs->ArgumentType) {
case NO_ARGUMENT:
// No value
- if (!this->PopulateVariable(cs, 0)) {
+ if (!this->PopulateVariable(cs, KWSYS_NULLPTR)) {
return 0;
}
break;
@@ -340,7 +340,7 @@ void CommandLineArguments::AddCallback(const char* argument,
s.Callback = callback;
s.CallData = call_data;
s.VariableType = CommandLineArguments::NO_VARIABLE_TYPE;
- s.Variable = 0;
+ s.Variable = KWSYS_NULLPTR;
s.Help = help;
this->Internals->Callbacks[argument] = s;
@@ -355,8 +355,8 @@ void CommandLineArguments::AddArgument(const char* argument,
CommandLineArgumentsCallbackStructure s;
s.Argument = argument;
s.ArgumentType = type;
- s.Callback = 0;
- s.CallData = 0;
+ s.Callback = KWSYS_NULLPTR;
+ s.CallData = KWSYS_NULLPTR;
s.VariableType = vtype;
s.Variable = variable;
s.Help = help;
@@ -427,7 +427,7 @@ const char* CommandLineArguments::GetHelp(const char* arg)
CommandLineArguments::Internal::CallbacksMap::iterator it =
this->Internals->Callbacks.find(arg);
if (it == this->Internals->Callbacks.end()) {
- return 0;
+ return KWSYS_NULLPTR;
}
// Since several arguments may point to the same argument, find the one this
@@ -529,10 +529,7 @@ void CommandLineArguments::GenerateHelp()
}
}
- // Create format for that string
- char format[80];
- sprintf(format, " %%-%us ", static_cast<unsigned int>(maxlen));
-
+ CommandLineArguments::Internal::String::size_type maxstrlen = maxlen;
maxlen += 4; // For the space before and after the option
// Print help for each option
@@ -540,27 +537,24 @@ void CommandLineArguments::GenerateHelp()
CommandLineArguments::Internal::SetOfStrings::iterator sit;
for (sit = mpit->second.begin(); sit != mpit->second.end(); sit++) {
str << std::endl;
- char argument[100];
- sprintf(argument, "%s", sit->c_str());
+ std::string argument = *sit;
switch (this->Internals->Callbacks[*sit].ArgumentType) {
case CommandLineArguments::NO_ARGUMENT:
break;
case CommandLineArguments::CONCAT_ARGUMENT:
- strcat(argument, "opt");
+ argument += "opt";
break;
case CommandLineArguments::SPACE_ARGUMENT:
- strcat(argument, " opt");
+ argument += " opt";
break;
case CommandLineArguments::EQUAL_ARGUMENT:
- strcat(argument, "=opt");
+ argument += "=opt";
break;
case CommandLineArguments::MULTI_ARGUMENT:
- strcat(argument, " opt opt ...");
+ argument += " opt opt ...";
break;
}
- char buffer[80];
- sprintf(buffer, format, argument);
- str << buffer;
+ str << " " << argument.substr(0, maxstrlen) << " ";
}
const char* ptr = this->Internals->Callbacks[mpit->first].Help;
size_t len = strlen(ptr);
@@ -627,7 +621,7 @@ void CommandLineArguments::PopulateVariable(bool* variable,
void CommandLineArguments::PopulateVariable(int* variable,
const std::string& value)
{
- char* res = 0;
+ char* res = KWSYS_NULLPTR;
*variable = static_cast<int>(strtol(value.c_str(), &res, 10));
// if ( res && *res )
// {
@@ -638,7 +632,7 @@ void CommandLineArguments::PopulateVariable(int* variable,
void CommandLineArguments::PopulateVariable(double* variable,
const std::string& value)
{
- char* res = 0;
+ char* res = KWSYS_NULLPTR;
*variable = strtod(value.c_str(), &res);
// if ( res && *res )
// {
@@ -649,10 +643,7 @@ void CommandLineArguments::PopulateVariable(double* variable,
void CommandLineArguments::PopulateVariable(char** variable,
const std::string& value)
{
- if (*variable) {
- delete[] * variable;
- *variable = 0;
- }
+ delete[] * variable;
*variable = new char[value.size() + 1];
strcpy(*variable, value.c_str());
}
@@ -678,7 +669,7 @@ void CommandLineArguments::PopulateVariable(std::vector<bool>* variable,
void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
const std::string& value)
{
- char* res = 0;
+ char* res = KWSYS_NULLPTR;
variable->push_back(static_cast<int>(strtol(value.c_str(), &res, 10)));
// if ( res && *res )
// {
@@ -689,7 +680,7 @@ void CommandLineArguments::PopulateVariable(std::vector<int>* variable,
void CommandLineArguments::PopulateVariable(std::vector<double>* variable,
const std::string& value)
{
- char* res = 0;
+ char* res = KWSYS_NULLPTR;
variable->push_back(strtod(value.c_str(), &res));
// if ( res && *res )
// {
diff --git a/Source/kwsys/Configure.h.in b/Source/kwsys/Configure.h.in
index 0afcae781..224047a7b 100644
--- a/Source/kwsys/Configure.h.in
+++ b/Source/kwsys/Configure.h.in
@@ -62,9 +62,6 @@
!defined(@KWSYS_NAMESPACE@_LFS_NO_DEFINE_FILE_OFFSET_BITS)
#define _FILE_OFFSET_BITS 64
#endif
-#if 0 && (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64)
-#error "_FILE_OFFSET_BITS must be defined to at least 64"
-#endif
#endif
#endif
diff --git a/Source/kwsys/Configure.hxx.in b/Source/kwsys/Configure.hxx.in
index 1c07a4ef7..05afc7d12 100644
--- a/Source/kwsys/Configure.hxx.in
+++ b/Source/kwsys/Configure.hxx.in
@@ -12,6 +12,37 @@
#define @KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H \
@KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H@
+#if defined(__SUNPRO_CC) && __SUNPRO_CC > 0x5130 && defined(__has_attribute)
+#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_attribute(x)
+#elif defined(__has_cpp_attribute)
+#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) __has_cpp_attribute(x)
+#else
+#define @KWSYS_NAMESPACE@__has_cpp_attribute(x) 0
+#endif
+
+#if __cplusplus >= 201103L
+#define @KWSYS_NAMESPACE@_NULLPTR nullptr
+#else
+#define @KWSYS_NAMESPACE@_NULLPTR 0
+#endif
+
+#ifndef @KWSYS_NAMESPACE@_FALLTHROUGH
+#if __cplusplus >= 201703L && @KWSYS_NAMESPACE@__has_cpp_attribute(fallthrough)
+#define @KWSYS_NAMESPACE@_FALLTHROUGH [[fallthrough]]
+#elif __cplusplus >= 201103L && \
+ @KWSYS_NAMESPACE@__has_cpp_attribute(gnu::fallthrough)
+#define @KWSYS_NAMESPACE@_FALLTHROUGH [[gnu::fallthrough]]
+#elif __cplusplus >= 201103L && \
+ @KWSYS_NAMESPACE@__has_cpp_attribute(clang::fallthrough)
+#define @KWSYS_NAMESPACE@_FALLTHROUGH [[clang::fallthrough]]
+#endif
+#endif
+#ifndef @KWSYS_NAMESPACE@_FALLTHROUGH
+#define @KWSYS_NAMESPACE@_FALLTHROUGH static_cast<void>(0)
+#endif
+
+#undef @KWSYS_NAMESPACE@__has_cpp_attribute
+
/* If building a C++ file in kwsys itself, give the source file
access to the macros without a configured namespace. */
#if defined(KWSYS_NAMESPACE)
@@ -22,6 +53,8 @@
#define KWSYS_STL_HAS_WSTRING @KWSYS_NAMESPACE@_STL_HAS_WSTRING
#define KWSYS_CXX_HAS_EXT_STDIO_FILEBUF_H \
@KWSYS_NAMESPACE@_CXX_HAS_EXT_STDIO_FILEBUF_H
+#define KWSYS_FALLTHROUGH @KWSYS_NAMESPACE@_FALLTHROUGH
+#define KWSYS_NULLPTR @KWSYS_NAMESPACE@_NULLPTR
#endif
#endif
diff --git a/Source/kwsys/ConsoleBuf.hxx.in b/Source/kwsys/ConsoleBuf.hxx.in
index 46d65a865..cf68146c4 100644
--- a/Source/kwsys/ConsoleBuf.hxx.in
+++ b/Source/kwsys/ConsoleBuf.hxx.in
@@ -264,6 +264,7 @@ private:
if (m_isConsoleInput) {
break;
}
+ @KWSYS_NAMESPACE@_FALLTHROUGH;
case FILE_TYPE_PIPE:
m_activeInputCodepage = input_pipe_codepage;
break;
@@ -290,6 +291,7 @@ private:
if (m_isConsoleOutput) {
break;
}
+ @KWSYS_NAMESPACE@_FALLTHROUGH;
case FILE_TYPE_PIPE:
m_activeOutputCodepage = output_pipe_codepage;
break;
diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx
index 69068aaf8..a84be1186 100644
--- a/Source/kwsys/Directory.cxx
+++ b/Source/kwsys/Directory.cxx
@@ -48,7 +48,7 @@ unsigned long Directory::GetNumberOfFiles() const
const char* Directory::GetFile(unsigned long dindex) const
{
if (dindex >= this->Internal->Files.size()) {
- return 0;
+ return KWSYS_NULLPTR;
}
return this->Internal->Files[dindex].c_str();
}
diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx
index 1b4596a4e..9b7d9bfc7 100644
--- a/Source/kwsys/DynamicLoader.cxx
+++ b/Source/kwsys/DynamicLoader.cxx
@@ -60,7 +60,7 @@ const char* DynamicLoader::LastError()
} // namespace KWSYS_NAMESPACE
#elif defined(__hpux)
-// Implementation for HPUX machines
+// Implementation for HPUX machines
#include <dl.h>
#include <errno.h>
@@ -163,17 +163,13 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
{
void* result = 0;
// Need to prepend symbols with '_' on Apple-gcc compilers
- size_t len = sym.size();
- char* rsym = new char[len + 1 + 1];
- strcpy(rsym, "_");
- strcat(rsym + 1, sym.c_str());
+ std::string rsym = '_' + sym;
- NSSymbol symbol = NSLookupSymbolInModule(lib, rsym);
+ NSSymbol symbol = NSLookupSymbolInModule(lib, rsym.c_str());
if (symbol) {
result = NSAddressOfSymbol(symbol);
}
- delete[] rsym;
// Hack to cast pointer-to-data to pointer-to-function.
return *reinterpret_cast<DynamicLoader::SymbolPointer*>(&result);
}
@@ -237,17 +233,12 @@ DynamicLoader::SymbolPointer DynamicLoader::GetSymbolAddress(
void* result;
#if defined(__BORLANDC__) || defined(__WATCOMC__)
// Need to prepend symbols with '_'
- size_t len = sym.size();
- char* rsym = new char[len + 1 + 1];
- strcpy(rsym, "_");
- strcat(rsym, sym.c_str());
+ std::string ssym = '_' + sym;
+ const char* rsym = ssym.c_str();
#else
const char* rsym = sym.c_str();
#endif
result = (void*)GetProcAddress(lib, rsym);
-#if defined(__BORLANDC__) || defined(__WATCOMC__)
- delete[] rsym;
-#endif
// Hack to cast pointer-to-data to pointer-to-function.
#ifdef __WATCOMC__
return *(DynamicLoader::SymbolPointer*)(&result);
diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in
index 7e71a4593..dc3469266 100644
--- a/Source/kwsys/DynamicLoader.hxx.in
+++ b/Source/kwsys/DynamicLoader.hxx.in
@@ -35,7 +35,7 @@ namespace @KWSYS_NAMESPACE@ {
* or absolute) pathname. Otherwise, the dynamic linker searches for the
* library as follows : see ld.so(8) for further details):
* Whereas this distinction does not exist on Win32. Therefore ideally you
- * should be doing full path to garantee to have a consistent way of dealing
+ * should be doing full path to guarantee to have a consistent way of dealing
* with dynamic loading of shared library.
*
* \warning the Cygwin implementation do not use the Win32 HMODULE. Put extra
@@ -72,7 +72,7 @@ public:
static LibraryHandle OpenLibrary(const std::string&);
/** Attempt to detach a dynamic library from the
- * process. A value of true is returned if it is sucessful. */
+ * process. A value of true is returned if it is successful. */
static int CloseLibrary(LibraryHandle);
/** Find the address of the symbol in the given library. */
diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx
index b1e54c958..a1fe040d2 100644
--- a/Source/kwsys/EncodingCXX.cxx
+++ b/Source/kwsys/EncodingCXX.cxx
@@ -65,7 +65,7 @@ Encoding::CommandLineArguments::CommandLineArguments(int ac,
for (int i = 0; i < ac; i++) {
this->argv_[i] = strdup(av[i]);
}
- this->argv_[ac] = 0;
+ this->argv_[ac] = KWSYS_NULLPTR;
}
Encoding::CommandLineArguments::CommandLineArguments(int ac,
@@ -75,7 +75,7 @@ Encoding::CommandLineArguments::CommandLineArguments(int ac,
for (int i = 0; i < ac; i++) {
this->argv_[i] = kwsysEncoding_DupToNarrow(av[i]);
}
- this->argv_[ac] = 0;
+ this->argv_[ac] = KWSYS_NULLPTR;
}
Encoding::CommandLineArguments::~CommandLineArguments()
@@ -90,7 +90,7 @@ Encoding::CommandLineArguments::CommandLineArguments(
{
this->argv_.resize(other.argv_.size());
for (size_t i = 0; i < this->argv_.size(); i++) {
- this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : 0;
+ this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : KWSYS_NULLPTR;
}
}
@@ -105,7 +105,7 @@ Encoding::CommandLineArguments& Encoding::CommandLineArguments::operator=(
this->argv_.resize(other.argv_.size());
for (i = 0; i < this->argv_.size(); i++) {
- this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : 0;
+ this->argv_[i] = other.argv_[i] ? strdup(other.argv_[i]) : KWSYS_NULLPTR;
}
}
@@ -193,7 +193,7 @@ std::string Encoding::ToNarrow(const std::wstring& str)
std::wstring Encoding::ToWide(const char* cstr)
{
std::wstring wstr;
- size_t length = kwsysEncoding_mbstowcs(0, cstr, 0) + 1;
+ size_t length = kwsysEncoding_mbstowcs(KWSYS_NULLPTR, cstr, 0) + 1;
if (length > 0) {
std::vector<wchar_t> wchars(length);
if (kwsysEncoding_mbstowcs(&wchars[0], cstr, length) > 0) {
@@ -206,7 +206,7 @@ std::wstring Encoding::ToWide(const char* cstr)
std::string Encoding::ToNarrow(const wchar_t* wcstr)
{
std::string str;
- size_t length = kwsysEncoding_wcstombs(0, wcstr, 0) + 1;
+ size_t length = kwsysEncoding_wcstombs(KWSYS_NULLPTR, wcstr, 0) + 1;
if (length > 0) {
std::vector<char> chars(length);
if (kwsysEncoding_wcstombs(&chars[0], wcstr, length) > 0) {
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index d2f0b8516..2b6db78cf 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -28,7 +28,7 @@
#include <string.h>
namespace KWSYS_NAMESPACE {
#if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
-// On Windows and apple, no difference between lower and upper case
+// On Windows and Apple, no difference between lower and upper case
#define KWSYS_GLOB_CASE_INDEPENDENT
#endif
@@ -81,13 +81,13 @@ std::string Glob::PatternToRegex(const std::string& pattern,
int c = *i;
if (c == '*') {
// A '*' (not between brackets) matches any string.
- // We modify this to not match slashes since the orignal glob
+ // We modify this to not match slashes since the original glob
// pattern documentation was meant for matching file name
// components separated by slashes.
regex += "[^/]*";
} else if (c == '?') {
// A '?' (not between brackets) matches any single character.
- // We modify this to not match slashes since the orignal glob
+ // We modify this to not match slashes since the original glob
// pattern documentation was meant for matching file name
// components separated by slashes.
regex += "[^/]";
@@ -201,7 +201,7 @@ bool Glob::RecurseDirectory(std::string::size_type start,
}
#if defined(KWSYS_GLOB_CASE_INDEPENDENT)
- // On Windows and apple, no difference between lower and upper case
+ // On Windows and Apple, no difference between lower and upper case
fname = kwsys::SystemTools::LowerCase(fname);
#endif
@@ -430,7 +430,7 @@ void Glob::SetRelative(const char* dir)
const char* Glob::GetRelative()
{
if (this->Relative.empty()) {
- return 0;
+ return KWSYS_NULLPTR;
}
return this->Relative.c_str();
}
diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in
index 237001c60..daf334a61 100644
--- a/Source/kwsys/Process.h.in
+++ b/Source/kwsys/Process.h.in
@@ -77,6 +77,7 @@
#define kwsysProcess_WaitForExit kwsys_ns(Process_WaitForExit)
#define kwsysProcess_Interrupt kwsys_ns(Process_Interrupt)
#define kwsysProcess_Kill kwsys_ns(Process_Kill)
+#define kwsysProcess_KillPID kwsys_ns(Process_KillPID)
#define kwsysProcess_ResetStartTime kwsys_ns(Process_ResetStartTime)
#endif
@@ -420,7 +421,7 @@ enum kwsysProcess_Pipes_e
/**
* Block until the child process terminates or the given timeout
- * expires. If no process is running, returns immediatly. The
+ * expires. If no process is running, returns immediately. The
* argument is:
*
* timeout = Specifies the maximum time this call may block. Upon
@@ -457,6 +458,13 @@ kwsysEXPORT void kwsysProcess_Interrupt(kwsysProcess* cp);
kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp);
/**
+ * Same as kwsysProcess_Kill using process ID to locate process to
+ * terminate.
+ * @see kwsysProcess_Kill(kwsysProcess* cp)
+ */
+kwsysEXPORT void kwsysProcess_KillPID(unsigned long);
+
+/**
* Reset the start time of the child process to the current time.
*/
kwsysEXPORT void kwsysProcess_ResetStartTime(kwsysProcess* cp);
diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c
index 3b32ca7d0..1e80b39cb 100644
--- a/Source/kwsys/ProcessUNIX.c
+++ b/Source/kwsys/ProcessUNIX.c
@@ -231,7 +231,7 @@ struct kwsysProcess_s
when reaping PIDs or modifying this array to avoid race conditions. */
volatile pid_t* volatile ForkPIDs;
- /* Flag for whether the children were terminated by a faild select. */
+ /* Flag for whether the children were terminated by a failed select. */
int SelectError;
/* The timeout length. */
@@ -359,9 +359,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
- if (cp->CommandExitCodes) {
- free(cp->CommandExitCodes);
- }
+ free(cp->CommandExitCodes);
free(cp->ProcessResults);
free(cp);
}
@@ -498,11 +496,10 @@ int kwsysProcess_SetWorkingDirectory(kwsysProcess* cp, const char* dir)
cp->WorkingDirectory = 0;
}
if (dir) {
- cp->WorkingDirectory = (char*)malloc(strlen(dir) + 1);
+ cp->WorkingDirectory = strdup(dir);
if (!cp->WorkingDirectory) {
return 0;
}
- strcpy(cp->WorkingDirectory, dir);
}
return 1;
}
@@ -531,11 +528,10 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int prPipe, const char* file)
*pfile = 0;
}
if (file) {
- *pfile = (char*)malloc(strlen(file) + 1);
+ *pfile = strdup(file);
if (!*pfile) {
return 0;
}
- strcpy(*pfile, file);
}
/* If we are redirecting the pipe, do not share it or use a native
@@ -1514,9 +1510,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
oldForkPIDs = cp->ForkPIDs;
cp->ForkPIDs = (volatile pid_t*)malloc(sizeof(volatile pid_t) *
(size_t)(cp->NumberOfCommands));
- if (oldForkPIDs) {
- kwsysProcessVolatileFree(oldForkPIDs);
- }
+ kwsysProcessVolatileFree(oldForkPIDs);
if (!cp->ForkPIDs) {
return 0;
}
@@ -1524,9 +1518,7 @@ static int kwsysProcessInitialize(kwsysProcess* cp)
cp->ForkPIDs[i] = 0; /* can't use memset due to volatile */
}
- if (cp->CommandExitCodes) {
- free(cp->CommandExitCodes);
- }
+ free(cp->CommandExitCodes);
cp->CommandExitCodes =
(int*)malloc(sizeof(int) * (size_t)(cp->NumberOfCommands));
if (!cp->CommandExitCodes) {
@@ -1938,6 +1930,7 @@ static int kwsysProcessSetupOutputPipeFile(int* p, const char* name)
/* Set close-on-exec flag on the pipe's end. */
if (fcntl(fout, F_SETFD, FD_CLOEXEC) < 0) {
+ close(fout);
return 0;
}
@@ -2033,7 +2026,15 @@ static kwsysProcessTime kwsysProcessTimeGetCurrent(void)
{
kwsysProcessTime current;
kwsysProcessTimeNative current_native;
+#if KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+ struct timespec current_timespec;
+ clock_gettime(CLOCK_MONOTONIC, &current_timespec);
+
+ current_native.tv_sec = current_timespec.tv_sec;
+ current_native.tv_usec = current_timespec.tv_nsec / 1000;
+#else
gettimeofday(&current_native, 0);
+#endif
current.tv_sec = (long)current_native.tv_sec;
current.tv_usec = (long)current_native.tv_usec;
return current;
@@ -2290,6 +2291,7 @@ static void kwsysProcessChildErrorExit(int errorPipe)
char buffer[KWSYSPE_PIPE_BUFFER_SIZE];
kwsysProcess_ssize_t result;
strncpy(buffer, strerror(errno), KWSYSPE_PIPE_BUFFER_SIZE);
+ buffer[KWSYSPE_PIPE_BUFFER_SIZE - 1] = '\0';
/* Report the error to the parent through the special pipe. */
result = write(errorPipe, buffer, strlen(buffer));
@@ -2483,6 +2485,11 @@ static pid_t kwsysProcessFork(kwsysProcess* cp,
#define KWSYSPE_PS_FORMAT "%d %d %*[^\n]\n"
#endif
+void kwsysProcess_KillPID(unsigned long process_id)
+{
+ kwsysProcessKill((pid_t)process_id);
+}
+
static void kwsysProcessKill(pid_t process_id)
{
#if defined(__linux__) || defined(__CYGWIN__)
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c
index 5183e3d2c..82fdc7478 100644
--- a/Source/kwsys/ProcessWin32.c
+++ b/Source/kwsys/ProcessWin32.c
@@ -523,9 +523,7 @@ void kwsysProcess_Delete(kwsysProcess* cp)
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDIN, 0);
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDOUT, 0);
kwsysProcess_SetPipeFile(cp, kwsysProcess_Pipe_STDERR, 0);
- if (cp->CommandExitCodes) {
- free(cp->CommandExitCodes);
- }
+ free(cp->CommandExitCodes);
free(cp->ProcessResults);
free(cp);
}
@@ -713,11 +711,10 @@ int kwsysProcess_SetPipeFile(kwsysProcess* cp, int pipe, const char* file)
*pfile = 0;
}
if (file) {
- *pfile = (char*)malloc(strlen(file) + 1);
+ *pfile = strdup(file);
if (!*pfile) {
return 0;
}
- strcpy(*pfile, file);
}
/* If we are redirecting the pipe, do not share it or use a native
@@ -1469,6 +1466,11 @@ void kwsysProcess_Kill(kwsysProcess* cp)
for them to exit. */
}
+void kwsysProcess_KillPID(unsigned long process_id)
+{
+ kwsysProcessKillTree((DWORD)process_id);
+}
+
/*
Function executed for each pipe's thread. Argument is a pointer to
the kwsysProcessPipeData instance for this thread.
@@ -1607,9 +1609,7 @@ int kwsysProcessInitialize(kwsysProcess* cp)
}
ZeroMemory(cp->ProcessInformation,
sizeof(PROCESS_INFORMATION) * cp->NumberOfCommands);
- if (cp->CommandExitCodes) {
- free(cp->CommandExitCodes);
- }
+ free(cp->CommandExitCodes);
cp->CommandExitCodes = (DWORD*)malloc(sizeof(DWORD) * cp->NumberOfCommands);
if (!cp->CommandExitCodes) {
return 0;
@@ -2362,9 +2362,7 @@ static int kwsysProcess_List__New_NT4(kwsysProcess_List* self)
static void kwsysProcess_List__Delete_NT4(kwsysProcess_List* self)
{
/* Free the process information buffer. */
- if (self->Buffer) {
- free(self->Buffer);
- }
+ free(self->Buffer);
}
static int kwsysProcess_List__Update_NT4(kwsysProcess_List* self)
diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx
index 26e84e04e..78cff1a01 100644
--- a/Source/kwsys/RegularExpression.cxx
+++ b/Source/kwsys/RegularExpression.cxx
@@ -37,18 +37,18 @@ namespace KWSYS_NAMESPACE {
RegularExpression::RegularExpression(const RegularExpression& rxp)
{
if (!rxp.program) {
- this->program = 0;
+ this->program = KWSYS_NULLPTR;
return;
}
int ind;
this->progsize = rxp.progsize; // Copy regular expression size
this->program = new char[this->progsize]; // Allocate storage
- for (ind = this->progsize; ind-- != 0;) // Copy regular expresion
+ for (ind = this->progsize; ind-- != 0;) // Copy regular expression
this->program[ind] = rxp.program[ind];
- this->startp[0] = rxp.startp[0]; // Copy pointers into last
- this->endp[0] = rxp.endp[0]; // Successful "find" operation
- this->regmust = rxp.regmust; // Copy field
- if (rxp.regmust != 0) {
+ // Copy pointers into last successful "find" operation
+ this->regmatch = rxp.regmatch;
+ this->regmust = rxp.regmust; // Copy field
+ if (rxp.regmust != KWSYS_NULLPTR) {
char* dum = rxp.program;
ind = 0;
while (dum != rxp.regmust) {
@@ -69,19 +69,19 @@ RegularExpression& RegularExpression::operator=(const RegularExpression& rxp)
return *this;
}
if (!rxp.program) {
- this->program = 0;
+ this->program = KWSYS_NULLPTR;
return *this;
}
int ind;
this->progsize = rxp.progsize; // Copy regular expression size
delete[] this->program;
this->program = new char[this->progsize]; // Allocate storage
- for (ind = this->progsize; ind-- != 0;) // Copy regular expresion
+ for (ind = this->progsize; ind-- != 0;) // Copy regular expression
this->program[ind] = rxp.program[ind];
- this->startp[0] = rxp.startp[0]; // Copy pointers into last
- this->endp[0] = rxp.endp[0]; // Successful "find" operation
- this->regmust = rxp.regmust; // Copy field
- if (rxp.regmust != 0) {
+ // Copy pointers into last successful "find" operation
+ this->regmatch = rxp.regmatch;
+ this->regmust = rxp.regmust; // Copy field
+ if (rxp.regmust != KWSYS_NULLPTR) {
char* dum = rxp.program;
ind = 0;
while (dum != rxp.regmust) {
@@ -123,12 +123,13 @@ bool RegularExpression::deep_equal(const RegularExpression& rxp) const
while (ind-- != 0) // Else while still characters
if (this->program[ind] != rxp.program[ind]) // If regexp are different
return false; // Return failure
- return (this->startp[0] == rxp.startp[0] && // Else if same start/end ptrs,
- this->endp[0] == rxp.endp[0]); // Return true
+ // Else if same start/end ptrs, return true
+ return (this->regmatch.start() == rxp.regmatch.start() &&
+ this->regmatch.end() == rxp.regmatch.end());
}
-// The remaining code in this file is derived from the regular expression code
-// whose copyright statement appears below. It has been changed to work
+// The remaining code in this file is derived from the regular expression code
+// whose copyright statement appears below. It has been changed to work
// with the class concepts of C++ and COOL.
/*
@@ -276,31 +277,35 @@ const unsigned char MAGIC = 0234;
/////////////////////////////////////////////////////////////////////////
/*
- * Global work variables for compile().
+ * Read only utility variables.
*/
-static const char* regparse; // Input-scan pointer.
-static int regnpar; // () count.
static char regdummy;
-static char* regcode; // Code-emit pointer; &regdummy = don't.
-static long regsize; // Code size.
+static char* const regdummyptr = &regdummy;
/*
- * Forward declarations for compile()'s friends.
+ * Utility class for RegularExpression::compile().
*/
-// #ifndef static
-// #define static static
-// #endif
-static char* reg(int, int*);
-static char* regbranch(int*);
-static char* regpiece(int*);
-static char* regatom(int*);
-static char* regnode(char);
+class RegExpCompile
+{
+public:
+ const char* regparse; // Input-scan pointer.
+ int regnpar; // () count.
+ char* regcode; // Code-emit pointer; regdummyptr = don't.
+ long regsize; // Code size.
+
+ char* reg(int, int*);
+ char* regbranch(int*);
+ char* regpiece(int*);
+ char* regatom(int*);
+ char* regnode(char);
+ void regc(char);
+ void reginsert(char, char*);
+ static void regtail(char*, const char*);
+ static void regoptail(char*, const char*);
+};
+
static const char* regnext(const char*);
static char* regnext(char*);
-static void regc(char);
-static void reginsert(char, char*);
-static void regtail(char*, const char*);
-static void regoptail(char*, const char*);
#ifdef STRCSPN
static int strcspn();
@@ -330,26 +335,27 @@ bool RegularExpression::compile(const char* exp)
size_t len;
int flags;
- if (exp == 0) {
+ if (exp == KWSYS_NULLPTR) {
// RAISE Error, SYM(RegularExpression), SYM(No_Expr),
printf("RegularExpression::compile(): No expression supplied.\n");
return false;
}
// First pass: determine size, legality.
- regparse = exp;
- regnpar = 1;
- regsize = 0L;
- regcode = &regdummy;
- regc(static_cast<char>(MAGIC));
- if (!reg(0, &flags)) {
+ RegExpCompile comp;
+ comp.regparse = exp;
+ comp.regnpar = 1;
+ comp.regsize = 0L;
+ comp.regcode = regdummyptr;
+ comp.regc(static_cast<char>(MAGIC));
+ if (!comp.reg(0, &flags)) {
printf("RegularExpression::compile(): Error in compile.\n");
return false;
}
- this->startp[0] = this->endp[0] = this->searchstring = 0;
+ this->regmatch.clear();
// Small enough for pointer-storage convention?
- if (regsize >= 32767L) { // Probably could be 65535L.
+ if (comp.regsize >= 32767L) { // Probably could be 65535L.
// RAISE Error, SYM(RegularExpression), SYM(Expr_Too_Big),
printf("RegularExpression::compile(): Expression too big.\n");
return false;
@@ -357,29 +363,29 @@ bool RegularExpression::compile(const char* exp)
// Allocate space.
//#ifndef _WIN32
- if (this->program != 0)
+ if (this->program != KWSYS_NULLPTR)
delete[] this->program;
//#endif
- this->program = new char[regsize];
- this->progsize = static_cast<int>(regsize);
+ this->program = new char[comp.regsize];
+ this->progsize = static_cast<int>(comp.regsize);
- if (this->program == 0) {
+ if (this->program == KWSYS_NULLPTR) {
// RAISE Error, SYM(RegularExpression), SYM(Out_Of_Memory),
printf("RegularExpression::compile(): Out of memory.\n");
return false;
}
// Second pass: emit code.
- regparse = exp;
- regnpar = 1;
- regcode = this->program;
- regc(static_cast<char>(MAGIC));
- reg(0, &flags);
+ comp.regparse = exp;
+ comp.regnpar = 1;
+ comp.regcode = this->program;
+ comp.regc(static_cast<char>(MAGIC));
+ comp.reg(0, &flags);
// Dig out information for optimizations.
this->regstart = '\0'; // Worst-case defaults.
this->reganch = 0;
- this->regmust = 0;
+ this->regmust = KWSYS_NULLPTR;
this->regmlen = 0;
scan = this->program + 1; // First BRANCH.
if (OP(regnext(scan)) == END) { // Only one top-level choice.
@@ -400,9 +406,9 @@ bool RegularExpression::compile(const char* exp)
// absence of others.
//
if (flags & SPSTART) {
- longest = 0;
+ longest = KWSYS_NULLPTR;
len = 0;
- for (; scan != 0; scan = regnext(scan))
+ for (; scan != KWSYS_NULLPTR; scan = regnext(scan))
if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
longest = OPERAND(scan);
len = strlen(OPERAND(scan));
@@ -423,7 +429,7 @@ bool RegularExpression::compile(const char* exp)
* is a trifle forced, but the need to tie the tails of the branches to what
* follows makes it hard to avoid.
*/
-static char* reg(int paren, int* flagp)
+char* RegExpCompile::reg(int paren, int* flagp)
{
char* ret;
char* br;
@@ -435,22 +441,22 @@ static char* reg(int paren, int* flagp)
// Make an OPEN node, if parenthesized.
if (paren) {
- if (regnpar >= RegularExpression::NSUBEXP) {
+ if (regnpar >= RegularExpressionMatch::NSUBEXP) {
// RAISE Error, SYM(RegularExpression), SYM(Too_Many_Parens),
printf("RegularExpression::compile(): Too many parentheses.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
parno = regnpar;
regnpar++;
ret = regnode(static_cast<char>(OPEN + parno));
} else
- ret = 0;
+ ret = KWSYS_NULLPTR;
// Pick up the branches, linking them together.
br = regbranch(&flags);
- if (br == 0)
- return (0);
- if (ret != 0)
+ if (br == KWSYS_NULLPTR)
+ return (KWSYS_NULLPTR);
+ if (ret != KWSYS_NULLPTR)
regtail(ret, br); // OPEN -> first.
else
ret = br;
@@ -460,8 +466,8 @@ static char* reg(int paren, int* flagp)
while (*regparse == '|') {
regparse++;
br = regbranch(&flags);
- if (br == 0)
- return (0);
+ if (br == KWSYS_NULLPTR)
+ return (KWSYS_NULLPTR);
regtail(ret, br); // BRANCH -> BRANCH.
if (!(flags & HASWIDTH))
*flagp &= ~HASWIDTH;
@@ -473,23 +479,23 @@ static char* reg(int paren, int* flagp)
regtail(ret, ender);
// Hook the tails of the branches to the closing node.
- for (br = ret; br != 0; br = regnext(br))
+ for (br = ret; br != KWSYS_NULLPTR; br = regnext(br))
regoptail(br, ender);
// Check for proper termination.
if (paren && *regparse++ != ')') {
// RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
printf("RegularExpression::compile(): Unmatched parentheses.\n");
- return 0;
+ return KWSYS_NULLPTR;
} else if (!paren && *regparse != '\0') {
if (*regparse == ')') {
// RAISE Error, SYM(RegularExpression), SYM(Unmatched_Parens),
printf("RegularExpression::compile(): Unmatched parentheses.\n");
- return 0;
+ return KWSYS_NULLPTR;
} else {
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf("RegularExpression::compile(): Internal error.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
// NOTREACHED
}
@@ -501,7 +507,7 @@ static char* reg(int paren, int* flagp)
*
* Implements the concatenation operator.
*/
-static char* regbranch(int* flagp)
+char* RegExpCompile::regbranch(int* flagp)
{
char* ret;
char* chain;
@@ -511,19 +517,19 @@ static char* regbranch(int* flagp)
*flagp = WORST; // Tentatively.
ret = regnode(BRANCH);
- chain = 0;
+ chain = KWSYS_NULLPTR;
while (*regparse != '\0' && *regparse != '|' && *regparse != ')') {
latest = regpiece(&flags);
- if (latest == 0)
- return (0);
+ if (latest == KWSYS_NULLPTR)
+ return (KWSYS_NULLPTR);
*flagp |= flags & HASWIDTH;
- if (chain == 0) // First piece.
+ if (chain == KWSYS_NULLPTR) // First piece.
*flagp |= flags & SPSTART;
else
regtail(chain, latest);
chain = latest;
}
- if (chain == 0) // Loop ran zero times.
+ if (chain == KWSYS_NULLPTR) // Loop ran zero times.
regnode(NOTHING);
return (ret);
@@ -538,7 +544,7 @@ static char* regbranch(int* flagp)
* It might seem that this node could be dispensed with entirely, but the
* endmarker role is not redundant.
*/
-static char* regpiece(int* flagp)
+char* RegExpCompile::regpiece(int* flagp)
{
char* ret;
char op;
@@ -546,8 +552,8 @@ static char* regpiece(int* flagp)
int flags;
ret = regatom(&flags);
- if (ret == 0)
- return (0);
+ if (ret == KWSYS_NULLPTR)
+ return (KWSYS_NULLPTR);
op = *regparse;
if (!ISMULT(op)) {
@@ -558,7 +564,7 @@ static char* regpiece(int* flagp)
if (!(flags & HASWIDTH) && op != '?') {
// RAISE Error, SYM(RegularExpression), SYM(Empty_Operand),
printf("RegularExpression::compile() : *+ operand could be empty.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
*flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
@@ -592,7 +598,7 @@ static char* regpiece(int* flagp)
if (ISMULT(*regparse)) {
// RAISE Error, SYM(RegularExpression), SYM(Nested_Operand),
printf("RegularExpression::compile(): Nested *?+.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
return (ret);
}
@@ -605,7 +611,7 @@ static char* regpiece(int* flagp)
* faster to run. Backslashed characters are exceptions, each becoming a
* separate node; the code is simpler that way and it's not worth fixing.
*/
-static char* regatom(int* flagp)
+char* RegExpCompile::regatom(int* flagp)
{
char* ret;
int flags;
@@ -645,7 +651,7 @@ static char* regatom(int* flagp)
if (rxpclass > rxpclassend + 1) {
// RAISE Error, SYM(RegularExpression), SYM(Invalid_Range),
printf("RegularExpression::compile(): Invalid range in [].\n");
- return 0;
+ return KWSYS_NULLPTR;
}
for (; rxpclass <= rxpclassend; rxpclass++)
regc(static_cast<char>(rxpclass));
@@ -658,15 +664,15 @@ static char* regatom(int* flagp)
if (*regparse != ']') {
// RAISE Error, SYM(RegularExpression), SYM(Unmatched_Bracket),
printf("RegularExpression::compile(): Unmatched [].\n");
- return 0;
+ return KWSYS_NULLPTR;
}
regparse++;
*flagp |= HASWIDTH | SIMPLE;
} break;
case '(':
ret = reg(1, &flags);
- if (ret == 0)
- return (0);
+ if (ret == KWSYS_NULLPTR)
+ return (KWSYS_NULLPTR);
*flagp |= flags & (HASWIDTH | SPSTART);
break;
case '\0':
@@ -674,18 +680,18 @@ static char* regatom(int* flagp)
case ')':
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf("RegularExpression::compile(): Internal error.\n"); // Never here
- return 0;
+ return KWSYS_NULLPTR;
case '?':
case '+':
case '*':
// RAISE Error, SYM(RegularExpression), SYM(No_Operand),
printf("RegularExpression::compile(): ?+* follows nothing.\n");
- return 0;
+ return KWSYS_NULLPTR;
case '\\':
if (*regparse == '\0') {
// RAISE Error, SYM(RegularExpression), SYM(Trailing_Backslash),
printf("RegularExpression::compile(): Trailing backslash.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
ret = regnode(EXACTLY);
regc(*regparse++);
@@ -701,7 +707,7 @@ static char* regatom(int* flagp)
if (len <= 0) {
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf("RegularExpression::compile(): Internal error.\n");
- return 0;
+ return KWSYS_NULLPTR;
}
ender = *(regparse + len);
if (len > 1 && ISMULT(ender))
@@ -724,13 +730,13 @@ static char* regatom(int* flagp)
- regnode - emit a node
Location.
*/
-static char* regnode(char op)
+char* RegExpCompile::regnode(char op)
{
char* ret;
char* ptr;
ret = regcode;
- if (ret == &regdummy) {
+ if (ret == regdummyptr) {
regsize += 3;
return (ret);
}
@@ -747,9 +753,9 @@ static char* regnode(char op)
/*
- regc - emit (if appropriate) a byte of code
*/
-static void regc(char b)
+void RegExpCompile::regc(char b)
{
- if (regcode != &regdummy)
+ if (regcode != regdummyptr)
*regcode++ = b;
else
regsize++;
@@ -760,13 +766,13 @@ static void regc(char b)
*
* Means relocating the operand.
*/
-static void reginsert(char op, char* opnd)
+void RegExpCompile::reginsert(char op, char* opnd)
{
char* src;
char* dst;
char* place;
- if (regcode == &regdummy) {
+ if (regcode == regdummyptr) {
regsize += 3;
return;
}
@@ -786,20 +792,20 @@ static void reginsert(char op, char* opnd)
/*
- regtail - set the next-pointer at the end of a node chain
*/
-static void regtail(char* p, const char* val)
+void RegExpCompile::regtail(char* p, const char* val)
{
char* scan;
char* temp;
int offset;
- if (p == &regdummy)
+ if (p == regdummyptr)
return;
// Find last node.
scan = p;
for (;;) {
temp = regnext(scan);
- if (temp == 0)
+ if (temp == KWSYS_NULLPTR)
break;
scan = temp;
}
@@ -815,10 +821,10 @@ static void regtail(char* p, const char* val)
/*
- regoptail - regtail on operand of first argument; nop if operandless
*/
-static void regoptail(char* p, const char* val)
+void RegExpCompile::regoptail(char* p, const char* val)
{
// "Operandless" and "op != BRANCH" are synonymous in practice.
- if (p == 0 || p == &regdummy || OP(p) != BRANCH)
+ if (p == KWSYS_NULLPTR || p == regdummyptr || OP(p) != BRANCH)
return;
regtail(OPERAND(p), val);
}
@@ -830,34 +836,30 @@ static void regoptail(char* p, const char* val)
////////////////////////////////////////////////////////////////////////
/*
- * Global work variables for find().
+ * Utility class for RegularExpression::find().
*/
-static const char* reginput; // String-input pointer.
-static const char* regbol; // Beginning of input, for ^ check.
-static const char** regstartp; // Pointer to startp array.
-static const char** regendp; // Ditto for endp.
+class RegExpFind
+{
+public:
+ const char* reginput; // String-input pointer.
+ const char* regbol; // Beginning of input, for ^ check.
+ const char** regstartp; // Pointer to startp array.
+ const char** regendp; // Ditto for endp.
-/*
- * Forwards.
- */
-static int regtry(const char*, const char**, const char**, const char*);
-static int regmatch(const char*);
-static int regrepeat(const char*);
-
-#ifdef DEBUG
-int regnarrate = 0;
-void regdump();
-static char* regprop();
-#endif
+ int regtry(const char*, const char**, const char**, const char*);
+ int regmatch(const char*);
+ int regrepeat(const char*);
+};
// find -- Matches the regular expression to the given string.
// Returns true if found, and sets start and end indexes accordingly.
-
-bool RegularExpression::find(const char* string)
+bool RegularExpression::find(char const* string,
+ RegularExpressionMatch& rmatch) const
{
const char* s;
- this->searchstring = string;
+ rmatch.clear();
+ rmatch.searchstring = string;
if (!this->program) {
return false;
@@ -868,54 +870,57 @@ bool RegularExpression::find(const char* string)
// RAISE Error, SYM(RegularExpression), SYM(Internal_Error),
printf(
"RegularExpression::find(): Compiled regular expression corrupted.\n");
- return 0;
+ return false;
}
// If there is a "must appear" string, look for it.
- if (this->regmust != 0) {
+ if (this->regmust != KWSYS_NULLPTR) {
s = string;
- while ((s = strchr(s, this->regmust[0])) != 0) {
+ while ((s = strchr(s, this->regmust[0])) != KWSYS_NULLPTR) {
if (strncmp(s, this->regmust, this->regmlen) == 0)
break; // Found it.
s++;
}
- if (s == 0) // Not present.
- return (0);
+ if (s == KWSYS_NULLPTR) // Not present.
+ return false;
}
+ RegExpFind regFind;
+
// Mark beginning of line for ^ .
- regbol = string;
+ regFind.regbol = string;
// Simplest case: anchored match need be tried only once.
if (this->reganch)
- return (regtry(string, this->startp, this->endp, this->program) != 0);
+ return (
+ regFind.regtry(string, rmatch.startp, rmatch.endp, this->program) != 0);
// Messy cases: unanchored match.
s = string;
if (this->regstart != '\0')
// We know what char it must start with.
- while ((s = strchr(s, this->regstart)) != 0) {
- if (regtry(s, this->startp, this->endp, this->program))
- return (1);
+ while ((s = strchr(s, this->regstart)) != KWSYS_NULLPTR) {
+ if (regFind.regtry(s, rmatch.startp, rmatch.endp, this->program))
+ return true;
s++;
}
else
// We don't -- general case.
do {
- if (regtry(s, this->startp, this->endp, this->program))
- return (1);
+ if (regFind.regtry(s, rmatch.startp, rmatch.endp, this->program))
+ return true;
} while (*s++ != '\0');
// Failure.
- return (0);
+ return false;
}
/*
- regtry - try match at specific point
0 failure, 1 success
*/
-static int regtry(const char* string, const char** start, const char** end,
- const char* prog)
+int RegExpFind::regtry(const char* string, const char** start,
+ const char** end, const char* prog)
{
int i;
const char** sp1;
@@ -927,9 +932,9 @@ static int regtry(const char* string, const char** start, const char** end,
sp1 = start;
ep = end;
- for (i = RegularExpression::NSUBEXP; i > 0; i--) {
- *sp1++ = 0;
- *ep++ = 0;
+ for (i = RegularExpressionMatch::NSUBEXP; i > 0; i--) {
+ *sp1++ = KWSYS_NULLPTR;
+ *ep++ = KWSYS_NULLPTR;
}
if (regmatch(prog + 1)) {
start[0] = string;
@@ -950,14 +955,14 @@ static int regtry(const char* string, const char** start, const char** end,
* by recursion.
* 0 failure, 1 success
*/
-static int regmatch(const char* prog)
+int RegExpFind::regmatch(const char* prog)
{
const char* scan; // Current node.
const char* next; // Next node.
scan = prog;
- while (scan != 0) {
+ while (scan != KWSYS_NULLPTR) {
next = regnext(scan);
@@ -989,12 +994,14 @@ static int regmatch(const char* prog)
reginput += len;
} break;
case ANYOF:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) == 0)
+ if (*reginput == '\0' ||
+ strchr(OPERAND(scan), *reginput) == KWSYS_NULLPTR)
return (0);
reginput++;
break;
case ANYBUT:
- if (*reginput == '\0' || strchr(OPERAND(scan), *reginput) != 0)
+ if (*reginput == '\0' ||
+ strchr(OPERAND(scan), *reginput) != KWSYS_NULLPTR)
return (0);
reginput++;
break;
@@ -1023,7 +1030,7 @@ static int regmatch(const char* prog)
// Don't set startp if some later invocation of the
// same parentheses already has.
//
- if (regstartp[no] == 0)
+ if (regstartp[no] == KWSYS_NULLPTR)
regstartp[no] = save;
return (1);
} else
@@ -1051,7 +1058,7 @@ static int regmatch(const char* prog)
// Don't set endp if some later invocation of the
// same parentheses already has.
//
- if (regendp[no] == 0)
+ if (regendp[no] == KWSYS_NULLPTR)
regendp[no] = save;
return (1);
} else
@@ -1071,7 +1078,7 @@ static int regmatch(const char* prog)
return (1);
reginput = save;
scan = regnext(scan);
- } while (scan != 0 && OP(scan) == BRANCH);
+ } while (scan != KWSYS_NULLPTR && OP(scan) == BRANCH);
return (0);
// NOTREACHED
}
@@ -1129,7 +1136,7 @@ static int regmatch(const char* prog)
/*
- regrepeat - repeatedly match something simple, report how many
*/
-static int regrepeat(const char* p)
+int RegExpFind::regrepeat(const char* p)
{
int count = 0;
const char* scan;
@@ -1149,13 +1156,13 @@ static int regrepeat(const char* p)
}
break;
case ANYOF:
- while (*scan != '\0' && strchr(opnd, *scan) != 0) {
+ while (*scan != '\0' && strchr(opnd, *scan) != KWSYS_NULLPTR) {
count++;
scan++;
}
break;
case ANYBUT:
- while (*scan != '\0' && strchr(opnd, *scan) == 0) {
+ while (*scan != '\0' && strchr(opnd, *scan) == KWSYS_NULLPTR) {
count++;
scan++;
}
@@ -1176,12 +1183,12 @@ static const char* regnext(const char* p)
{
int offset;
- if (p == &regdummy)
- return (0);
+ if (p == regdummyptr)
+ return (KWSYS_NULLPTR);
offset = NEXT(p);
if (offset == 0)
- return (0);
+ return (KWSYS_NULLPTR);
if (OP(p) == BACK)
return (p - offset);
@@ -1193,12 +1200,12 @@ static char* regnext(char* p)
{
int offset;
- if (p == &regdummy)
- return (0);
+ if (p == regdummyptr)
+ return (KWSYS_NULLPTR);
offset = NEXT(p);
if (offset == 0)
- return (0);
+ return (KWSYS_NULLPTR);
if (OP(p) == BACK)
return (p - offset);
diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in
index 606e3da6e..3cbbeb8b6 100644
--- a/Source/kwsys/RegularExpression.hxx.in
+++ b/Source/kwsys/RegularExpression.hxx.in
@@ -34,6 +34,115 @@
namespace @KWSYS_NAMESPACE@ {
+// Forward declaration
+class RegularExpression;
+
+/** \class RegularExpressionMatch
+ * \brief Stores the pattern matches of a RegularExpression
+ */
+class @KWSYS_NAMESPACE@_EXPORT RegularExpressionMatch
+{
+public:
+ RegularExpressionMatch();
+
+ bool isValid() const;
+ void clear();
+
+ std::string::size_type start() const;
+ std::string::size_type end() const;
+ std::string::size_type start(int n) const;
+ std::string::size_type end(int n) const;
+ std::string match(int n) const;
+
+ enum
+ {
+ NSUBEXP = 10
+ };
+
+private:
+ friend class RegularExpression;
+ const char* startp[NSUBEXP];
+ const char* endp[NSUBEXP];
+ const char* searchstring;
+};
+
+/**
+ * \brief Creates an invalid match object
+ */
+inline RegularExpressionMatch::RegularExpressionMatch()
+{
+ startp[0] = 0;
+ endp[0] = 0;
+ searchstring = 0;
+}
+
+/**
+ * \brief Returns true if the match pointers are valid
+ */
+inline bool RegularExpressionMatch::isValid() const
+{
+ return (this->startp[0] != 0);
+}
+
+/**
+ * \brief Resets to the (invalid) construction state.
+ */
+inline void RegularExpressionMatch::clear()
+{
+ startp[0] = 0;
+ endp[0] = 0;
+ searchstring = 0;
+}
+
+/**
+ * \brief Returns the start index of the full match.
+ */
+inline std::string::size_type RegularExpressionMatch::start() const
+{
+ return static_cast<std::string::size_type>(this->startp[0] - searchstring);
+}
+
+/**
+ * \brief Returns the end index of the full match.
+ */
+inline std::string::size_type RegularExpressionMatch::end() const
+{
+ return static_cast<std::string::size_type>(this->endp[0] - searchstring);
+}
+
+/**
+ * \brief Returns the start index of nth submatch.
+ * start(0) is the start of the full match.
+ */
+inline std::string::size_type RegularExpressionMatch::start(int n) const
+{
+ return static_cast<std::string::size_type>(this->startp[n] -
+ this->searchstring);
+}
+
+/**
+ * \brief Returns the end index of nth submatch.
+ * end(0) is the end of the full match.
+ */
+inline std::string::size_type RegularExpressionMatch::end(int n) const
+{
+ return static_cast<std::string::size_type>(this->endp[n] -
+ this->searchstring);
+}
+
+/**
+ * \brief Returns the nth submatch as a string.
+ */
+inline std::string RegularExpressionMatch::match(int n) const
+{
+ if (this->startp[n] == 0) {
+ return std::string();
+ } else {
+ return std::string(this->startp[n], static_cast<std::string::size_type>(
+ this->endp[n] - this->startp[n]));
+ }
+}
+
/** \class RegularExpression
* \brief Implements pattern matching with regular expressions.
*
@@ -93,7 +202,7 @@ namespace @KWSYS_NAMESPACE@ {
*
* ? Matches preceding pattern zero or once only
*
- * () Saves a matched expression and uses it in a later match
+ * () Saves a matched expression and uses it in a later match
*
* Note that more than one of these metacharacters can be used
* in a single regular expression in order to create complex
@@ -109,12 +218,12 @@ namespace @KWSYS_NAMESPACE@ {
* object as an argument and creates an object initialized with the
* information from the given RegularExpression object.
*
- * The find member function finds the first occurence of the regualr
+ * The find member function finds the first occurrence of the regular
* expression of that object in the string given to find as an argument. Find
* returns a boolean, and if true, mutates the private data appropriately.
* Find sets pointers to the beginning and end of the thing last found, they
* are pointers into the actual string that was searched. The start and end
- * member functions return indicies into the searched string that correspond
+ * member functions return indices into the searched string that correspond
* to the beginning and end pointers respectively. The compile member
* function takes a char* and puts the compiled version of the char* argument
* into the object's private data fields. The == and != operators only check
@@ -170,6 +279,9 @@ namespace @KWSYS_NAMESPACE@ {
* the same as the two characters before the first p encounterd in
* the line. It would match "drepa qrepb" in "rep drepa qrepb".
*
+ * All methods of RegularExpression can be called simultaneously from
+ * different threads but only if each invocation uses an own instance of
+ * RegularExpression.
*/
class @KWSYS_NAMESPACE@_EXPORT RegularExpression
{
@@ -213,9 +325,19 @@ public:
/**
* Matches the regular expression to the given string.
+ * Returns true if found, and sets start and end indexes
+ * in the RegularExpressionMatch instance accordingly.
+ *
+ * This method is thread safe when called with different
+ * RegularExpressionMatch instances.
+ */
+ bool find(char const*, RegularExpressionMatch&) const;
+
+ /**
+ * Matches the regular expression to the given string.
* Returns true if found, and sets start and end indexes accordingly.
*/
- bool find(char const*);
+ inline bool find(char const*);
/**
* Matches the regular expression to the given std string.
@@ -224,14 +346,18 @@ public:
inline bool find(std::string const&);
/**
- * Index to start of first find.
+ * Match indices
*/
+ inline RegularExpressionMatch const& regMatch() const;
inline std::string::size_type start() const;
+ inline std::string::size_type end() const;
+ inline std::string::size_type start(int n) const;
+ inline std::string::size_type end(int n) const;
/**
- * Index to end of first find.
+ * Match strings
*/
- inline std::string::size_type end() const;
+ inline std::string match(int n) const;
/**
* Copy the given regular expression.
@@ -266,29 +392,14 @@ public:
*/
inline void set_invalid();
- /**
- * Destructor.
- */
- // awf added
- std::string::size_type start(int n) const;
- std::string::size_type end(int n) const;
- std::string match(int n) const;
-
- enum
- {
- NSUBEXP = 10
- };
-
private:
- const char* startp[NSUBEXP];
- const char* endp[NSUBEXP];
+ RegularExpressionMatch regmatch;
char regstart; // Internal use only
char reganch; // Internal use only
const char* regmust; // Internal use only
std::string::size_type regmlen; // Internal use only
char* program;
int progsize;
- const char* searchstring;
};
/**
@@ -344,51 +455,42 @@ inline bool RegularExpression::compile(std::string const& s)
* Matches the regular expression to the given std string.
* Returns true if found, and sets start and end indexes accordingly.
*/
-inline bool RegularExpression::find(std::string const& s)
+inline bool RegularExpression::find(const char* s)
{
- return this->find(s.c_str());
+ return this->find(s, this->regmatch);
}
/**
- * Set the start position for the regular expression.
+ * Matches the regular expression to the given std string.
+ * Returns true if found, and sets start and end indexes accordingly.
*/
-inline std::string::size_type RegularExpression::start() const
+inline bool RegularExpression::find(std::string const& s)
{
- return static_cast<std::string::size_type>(this->startp[0] - searchstring);
+ return this->find(s.c_str());
}
/**
- * Returns the start/end index of the last item found.
+ * Returns the internal match object
*/
-inline std::string::size_type RegularExpression::end() const
+inline RegularExpressionMatch const& RegularExpression::regMatch() const
{
- return static_cast<std::string::size_type>(this->endp[0] - searchstring);
+ return this->regmatch;
}
/**
- * Returns true if two regular expressions have different
- * compiled program for pattern matching.
+ * Returns the start index of the full match.
*/
-inline bool RegularExpression::operator!=(const RegularExpression& r) const
+inline std::string::size_type RegularExpression::start() const
{
- return (!(*this == r));
+ return regmatch.start();
}
/**
- * Returns true if a valid regular expression is compiled
- * and ready for pattern matching.
+ * Returns the end index of the full match.
*/
-inline bool RegularExpression::is_valid() const
-{
- return (this->program != 0);
-}
-
-inline void RegularExpression::set_invalid()
+inline std::string::size_type RegularExpression::end() const
{
- //#ifndef _WIN32
- delete[] this->program;
- //#endif
- this->program = 0;
+ return regmatch.end();
}
/**
@@ -396,7 +498,7 @@ inline void RegularExpression::set_invalid()
*/
inline std::string::size_type RegularExpression::start(int n) const
{
- return static_cast<std::string::size_type>(this->startp[n] - searchstring);
+ return regmatch.start(n);
}
/**
@@ -404,7 +506,7 @@ inline std::string::size_type RegularExpression::start(int n) const
*/
inline std::string::size_type RegularExpression::end(int n) const
{
- return static_cast<std::string::size_type>(this->endp[n] - searchstring);
+ return regmatch.end(n);
}
/**
@@ -412,12 +514,33 @@ inline std::string::size_type RegularExpression::end(int n) const
*/
inline std::string RegularExpression::match(int n) const
{
- if (this->startp[n] == 0) {
- return std::string("");
- } else {
- return std::string(this->startp[n], static_cast<std::string::size_type>(
- this->endp[n] - this->startp[n]));
- }
+ return regmatch.match(n);
+}
+
+/**
+ * Returns true if two regular expressions have different
+ * compiled program for pattern matching.
+ */
+inline bool RegularExpression::operator!=(const RegularExpression& r) const
+{
+ return (!(*this == r));
+}
+
+/**
+ * Returns true if a valid regular expression is compiled
+ * and ready for pattern matching.
+ */
+inline bool RegularExpression::is_valid() const
+{
+ return (this->program != 0);
+}
+
+inline void RegularExpression::set_invalid()
+{
+ //#ifndef _WIN32
+ delete[] this->program;
+ //#endif
+ this->program = 0;
}
} // namespace @KWSYS_NAMESPACE@
diff --git a/Source/kwsys/SharedForward.h.in b/Source/kwsys/SharedForward.h.in
index f638267ec..0caf5e7c3 100644
--- a/Source/kwsys/SharedForward.h.in
+++ b/Source/kwsys/SharedForward.h.in
@@ -225,7 +225,7 @@ static const char kwsys_shared_forward_path_slash[2] = {
#define KWSYS_SHARED_FORWARD_LDD_N 1
#define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
-/* OSX */
+/* OS X */
#elif defined(__APPLE__)
#define KWSYS_SHARED_FORWARD_LDD "otool", "-L"
#define KWSYS_SHARED_FORWARD_LDD_N 2
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 86fdccdc7..2b9d7b174 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -121,7 +121,11 @@ typedef int siginfo_t;
#if defined(KWSYS_SYS_HAS_IFADDRS_H)
#include <ifaddrs.h>
#include <net/if.h>
-#if !defined(__LSB_VERSION__) /* LSB has no getifaddrs */
+#if defined(__LSB_VERSION__)
+/* LSB has no getifaddrs */
+#elif defined(__ANDROID_API__) && __ANDROID_API__ < 24
+/* Android has no getifaddrs prior to API 24. */
+#else
#define KWSYS_SYSTEMINFORMATION_IMPLEMENT_FQDN
#endif
#endif
@@ -340,7 +344,7 @@ public:
bool DoesCPUSupportCPUID();
- // Retrieve memory information in megabyte.
+ // Retrieve memory information in MiB.
size_t GetTotalVirtualMemory();
size_t GetAvailableVirtualMemory();
size_t GetTotalPhysicalMemory();
@@ -348,7 +352,7 @@ public:
LongLong GetProcessId();
- // Retrieve memory information in kib
+ // Retrieve memory information in KiB.
LongLong GetHostMemoryTotal();
LongLong GetHostMemoryAvailable(const char* envVarName);
LongLong GetHostMemoryUsed();
@@ -736,7 +740,7 @@ bool SystemInformation::DoesCPUSupportCPUID()
return this->Implementation->DoesCPUSupportCPUID();
}
-// Retrieve memory information in megabyte.
+// Retrieve memory information in MiB.
size_t SystemInformation::GetTotalVirtualMemory()
{
return this->Implementation->GetTotalVirtualMemory();
@@ -881,7 +885,7 @@ int LoadLines(FILE* file, std::vector<std::string>& lines)
char buf[bufSize] = { '\0' };
while (!feof(file) && !ferror(file)) {
errno = 0;
- if (fgets(buf, bufSize, file) == 0) {
+ if (fgets(buf, bufSize, file) == KWSYS_NULLPTR) {
if (ferror(file) && (errno == EINTR)) {
clearerr(file);
}
@@ -977,7 +981,7 @@ int GetFieldsFromCommand(const char* command, const char** fieldNames,
T* values)
{
FILE* file = popen(command, "r");
- if (file == 0) {
+ if (file == KWSYS_NULLPTR) {
return -1;
}
std::vector<std::string> fields;
@@ -987,7 +991,7 @@ int GetFieldsFromCommand(const char* command, const char** fieldNames,
return -1;
}
int i = 0;
- while (fieldNames[i] != NULL) {
+ while (fieldNames[i] != KWSYS_NULLPTR) {
int ierr = NameValue(fields, fieldNames[i], values[i]);
if (ierr) {
return -(i + 2);
@@ -1023,7 +1027,8 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
break;
case SIGFPE:
- oss << "Caught SIGFPE at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ oss << "Caught SIGFPE at "
+ << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
#if defined(FPE_INTDIV)
@@ -1071,7 +1076,8 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
break;
case SIGSEGV:
- oss << "Caught SIGSEGV at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ oss << "Caught SIGSEGV at "
+ << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case SEGV_MAPERR:
@@ -1089,7 +1095,8 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
break;
case SIGBUS:
- oss << "Caught SIGBUS at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ oss << "Caught SIGBUS at "
+ << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case BUS_ADRALN:
@@ -1129,7 +1136,8 @@ void StacktraceSignalHandler(int sigNo, siginfo_t* sigInfo,
break;
case SIGILL:
- oss << "Caught SIGILL at " << (sigInfo->si_addr == 0 ? "0x" : "")
+ oss << "Caught SIGILL at "
+ << (sigInfo->si_addr == KWSYS_NULLPTR ? "0x" : "")
<< sigInfo->si_addr << " ";
switch (sigInfo->si_code) {
case ILL_ILLOPC:
@@ -1313,8 +1321,8 @@ SymbolProperties::SymbolProperties()
// not using an initializer list
// to avoid some PGI compiler warnings
this->SetBinary("???");
- this->SetBinaryBaseAddress(NULL);
- this->Address = NULL;
+ this->SetBinaryBaseAddress(KWSYS_NULLPTR);
+ this->Address = KWSYS_NULLPTR;
this->SetSourceFile("???");
this->SetFunction("???");
this->SetLineNumber(-1);
@@ -1346,7 +1354,7 @@ std::string SymbolProperties::GetBinary() const
std::string binary;
char buf[1024] = { '\0' };
ssize_t ll = 0;
- if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0) {
+ if ((ll = readlink("/proc/self/exe", buf, 1024)) > 0 && ll < 1024) {
buf[ll] = '\0';
binary = buf;
} else {
@@ -1649,7 +1657,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
// any number of interfaces on this system we look for the
// first of these that contains the name returned by gethostname
// and is longer. failing that we return gethostname and indicate
- // with a failure code. Return of a failure code is not necessarilly
+ // with a failure code. Return of a failure code is not necessarily
// an indication of an error. for instance gethostname may return
// the fully qualified domain name, or there may not be one if the
// system lives on a private network such as in the case of a cluster
@@ -1671,7 +1679,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
return -2;
}
- for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
+ for (ifa = ifas; ifa != KWSYS_NULLPTR; ifa = ifa->ifa_next) {
int fam = ifa->ifa_addr ? ifa->ifa_addr->sa_family : -1;
// Skip Loopback interfaces
if (((fam == AF_INET) || (fam == AF_INET6)) &&
@@ -1682,7 +1690,7 @@ int SystemInformationImplementation::GetFullyQualifiedDomainName(
: sizeof(struct sockaddr_in6));
ierr = getnameinfo(ifa->ifa_addr, static_cast<socklen_t>(addrlen), host,
- NI_MAXHOST, NULL, 0, NI_NAMEREQD);
+ NI_MAXHOST, KWSYS_NULLPTR, 0, NI_NAMEREQD);
if (ierr) {
// don't report the failure now since we may succeed on another
// interface. If all attempts fail then return the failure code.
@@ -3609,7 +3617,7 @@ SystemInformationImplementation::GetHostMemoryTotal()
#elif defined(__APPLE__)
uint64_t mem;
size_t len = sizeof(mem);
- int ierr = sysctlbyname("hw.memsize", &mem, &len, NULL, 0);
+ int ierr = sysctlbyname("hw.memsize", &mem, &len, KWSYS_NULLPTR, 0);
if (ierr) {
return -1;
}
@@ -3633,7 +3641,7 @@ SystemInformationImplementation::GetHostMemoryAvailable(
// apply resource limits across groups of processes.
// this is of use on certain SMP systems (eg. SGI UV)
// where the host has a large amount of ram but a given user's
- // access to it is severly restricted. The system will
+ // access to it is severely restricted. The system will
// apply a limit across a set of processes. Units are in KiB.
if (hostLimitEnvVarName) {
const char* hostLimitEnvVarValue = getenv(hostLimitEnvVarName);
@@ -3752,7 +3760,8 @@ SystemInformationImplementation::GetHostMemoryUsed()
if (psz < 1) {
return -1;
}
- const char* names[3] = { "Pages wired down:", "Pages active:", NULL };
+ const char* names[3] = { "Pages wired down:", "Pages active:",
+ KWSYS_NULLPTR };
SystemInformation::LongLong values[2] = { SystemInformation::LongLong(0) };
int ierr = GetFieldsFromCommand("vm_stat", names, values);
if (ierr) {
@@ -3800,7 +3809,7 @@ SystemInformationImplementation::GetProcMemoryUsed()
std::ostringstream oss;
oss << "ps -o rss= -p " << pid;
FILE* file = popen(oss.str().c_str(), "r");
- if (file == 0) {
+ if (file == KWSYS_NULLPTR) {
return -1;
}
oss.str("");
@@ -3933,13 +3942,13 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
if (enable && !saOrigValid) {
// save the current actions
- sigaction(SIGABRT, 0, &saABRTOrig);
- sigaction(SIGSEGV, 0, &saSEGVOrig);
- sigaction(SIGTERM, 0, &saTERMOrig);
- sigaction(SIGINT, 0, &saINTOrig);
- sigaction(SIGILL, 0, &saILLOrig);
- sigaction(SIGBUS, 0, &saBUSOrig);
- sigaction(SIGFPE, 0, &saFPEOrig);
+ sigaction(SIGABRT, KWSYS_NULLPTR, &saABRTOrig);
+ sigaction(SIGSEGV, KWSYS_NULLPTR, &saSEGVOrig);
+ sigaction(SIGTERM, KWSYS_NULLPTR, &saTERMOrig);
+ sigaction(SIGINT, KWSYS_NULLPTR, &saINTOrig);
+ sigaction(SIGILL, KWSYS_NULLPTR, &saILLOrig);
+ sigaction(SIGBUS, KWSYS_NULLPTR, &saBUSOrig);
+ sigaction(SIGFPE, KWSYS_NULLPTR, &saFPEOrig);
// enable read, disable write
saOrigValid = 1;
@@ -3953,22 +3962,22 @@ void SystemInformationImplementation::SetStackTraceOnError(int enable)
#endif
sigemptyset(&sa.sa_mask);
- sigaction(SIGABRT, &sa, 0);
- sigaction(SIGSEGV, &sa, 0);
- sigaction(SIGTERM, &sa, 0);
- sigaction(SIGINT, &sa, 0);
- sigaction(SIGILL, &sa, 0);
- sigaction(SIGBUS, &sa, 0);
- sigaction(SIGFPE, &sa, 0);
+ sigaction(SIGABRT, &sa, KWSYS_NULLPTR);
+ sigaction(SIGSEGV, &sa, KWSYS_NULLPTR);
+ sigaction(SIGTERM, &sa, KWSYS_NULLPTR);
+ sigaction(SIGINT, &sa, KWSYS_NULLPTR);
+ sigaction(SIGILL, &sa, KWSYS_NULLPTR);
+ sigaction(SIGBUS, &sa, KWSYS_NULLPTR);
+ sigaction(SIGFPE, &sa, KWSYS_NULLPTR);
} else if (!enable && saOrigValid) {
// restore previous actions
- sigaction(SIGABRT, &saABRTOrig, 0);
- sigaction(SIGSEGV, &saSEGVOrig, 0);
- sigaction(SIGTERM, &saTERMOrig, 0);
- sigaction(SIGINT, &saINTOrig, 0);
- sigaction(SIGILL, &saILLOrig, 0);
- sigaction(SIGBUS, &saBUSOrig, 0);
- sigaction(SIGFPE, &saFPEOrig, 0);
+ sigaction(SIGABRT, &saABRTOrig, KWSYS_NULLPTR);
+ sigaction(SIGSEGV, &saSEGVOrig, KWSYS_NULLPTR);
+ sigaction(SIGTERM, &saTERMOrig, KWSYS_NULLPTR);
+ sigaction(SIGINT, &saINTOrig, KWSYS_NULLPTR);
+ sigaction(SIGILL, &saILLOrig, KWSYS_NULLPTR);
+ sigaction(SIGBUS, &saBUSOrig, KWSYS_NULLPTR);
+ sigaction(SIGFPE, &saFPEOrig, KWSYS_NULLPTR);
// enable write, disable read
saOrigValid = 0;
@@ -4404,7 +4413,7 @@ bool SystemInformationImplementation::ParseSysCtl()
int err = 0;
uint64_t value = 0;
size_t len = sizeof(value);
- sysctlbyname("hw.memsize", &value, &len, NULL, 0);
+ sysctlbyname("hw.memsize", &value, &len, KWSYS_NULLPTR, 0);
this->TotalPhysicalMemory = static_cast<size_t>(value / 1048576);
// Parse values for Mac
@@ -4414,7 +4423,7 @@ bool SystemInformationImplementation::ParseSysCtl()
if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmstat,
&count) == KERN_SUCCESS) {
len = sizeof(value);
- err = sysctlbyname("hw.pagesize", &value, &len, NULL, 0);
+ err = sysctlbyname("hw.pagesize", &value, &len, KWSYS_NULLPTR, 0);
int64_t available_memory = vmstat.free_count * value;
this->AvailablePhysicalMemory =
static_cast<size_t>(available_memory / 1048576);
@@ -4426,7 +4435,7 @@ bool SystemInformationImplementation::ParseSysCtl()
size_t miblen = sizeof(mib) / sizeof(mib[0]);
struct xsw_usage swap;
len = sizeof(swap);
- err = sysctl(mib, miblen, &swap, &len, NULL, 0);
+ err = sysctl(mib, miblen, &swap, &len, KWSYS_NULLPTR, 0);
if (err == 0) {
this->AvailableVirtualMemory =
static_cast<size_t>(swap.xsu_avail / 1048576);
@@ -4439,71 +4448,75 @@ bool SystemInformationImplementation::ParseSysCtl()
// CPU Info
len = sizeof(this->NumberOfPhysicalCPU);
- sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len, NULL, 0);
+ sysctlbyname("hw.physicalcpu", &this->NumberOfPhysicalCPU, &len,
+ KWSYS_NULLPTR, 0);
len = sizeof(this->NumberOfLogicalCPU);
- sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, NULL, 0);
+ sysctlbyname("hw.logicalcpu", &this->NumberOfLogicalCPU, &len, KWSYS_NULLPTR,
+ 0);
int cores_per_package = 0;
len = sizeof(cores_per_package);
err = sysctlbyname("machdep.cpu.cores_per_package", &cores_per_package, &len,
- NULL, 0);
+ KWSYS_NULLPTR, 0);
// That name was not found, default to 1
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical =
err != 0 ? 1 : static_cast<unsigned char>(cores_per_package);
len = sizeof(value);
- sysctlbyname("hw.cpufrequency", &value, &len, NULL, 0);
+ sysctlbyname("hw.cpufrequency", &value, &len, KWSYS_NULLPTR, 0);
this->CPUSpeedInMHz = static_cast<float>(value) / 1000000;
// Chip family
len = sizeof(this->ChipID.Family);
// Seems only the intel chips will have this name so if this fails it is
// probably a PPC machine
- err =
- sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len,
+ KWSYS_NULLPTR, 0);
if (err != 0) // Go back to names we know but are less descriptive
{
this->ChipID.Family = 0;
::memset(retBuf, 0, 128);
len = 32;
- err = sysctlbyname("hw.machine", &retBuf, &len, NULL, 0);
+ err = sysctlbyname("hw.machine", &retBuf, &len, KWSYS_NULLPTR, 0);
std::string machineBuf(retBuf);
if (machineBuf.find_first_of("Power") != std::string::npos) {
this->ChipID.Vendor = "IBM";
len = sizeof(this->ChipID.Family);
- err = sysctlbyname("hw.cputype", &this->ChipID.Family, &len, NULL, 0);
+ err = sysctlbyname("hw.cputype", &this->ChipID.Family, &len,
+ KWSYS_NULLPTR, 0);
len = sizeof(this->ChipID.Model);
- err = sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len, NULL, 0);
+ err = sysctlbyname("hw.cpusubtype", &this->ChipID.Model, &len,
+ KWSYS_NULLPTR, 0);
this->FindManufacturer();
}
} else // Should be an Intel Chip.
{
len = sizeof(this->ChipID.Family);
- err =
- sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.family", &this->ChipID.Family, &len,
+ KWSYS_NULLPTR, 0);
::memset(retBuf, 0, 128);
len = 128;
- err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.vendor", retBuf, &len, KWSYS_NULLPTR, 0);
// Chip Vendor
this->ChipID.Vendor = retBuf;
this->FindManufacturer();
// Chip Model
len = sizeof(value);
- err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.model", &value, &len, KWSYS_NULLPTR, 0);
this->ChipID.Model = static_cast<int>(value);
// Chip Stepping
len = sizeof(value);
value = 0;
- err = sysctlbyname("machdep.cpu.stepping", &value, &len, NULL, 0);
+ err = sysctlbyname("machdep.cpu.stepping", &value, &len, KWSYS_NULLPTR, 0);
if (!err) {
this->ChipID.Revision = static_cast<int>(value);
}
// feature string
- char* buf = 0;
+ char* buf = KWSYS_NULLPTR;
size_t allocSize = 128;
err = 0;
@@ -4520,7 +4533,8 @@ bool SystemInformationImplementation::ParseSysCtl()
}
buf[0] = ' ';
len = allocSize - 2; // keep space for leading and trailing space
- err = sysctlbyname("machdep.cpu.features", buf + 1, &len, NULL, 0);
+ err =
+ sysctlbyname("machdep.cpu.features", buf + 1, &len, KWSYS_NULLPTR, 0);
}
if (!err && buf && len) {
// now we can match every flags as space + flag + space
@@ -4561,7 +4575,8 @@ bool SystemInformationImplementation::ParseSysCtl()
// brand string
::memset(retBuf, 0, sizeof(retBuf));
len = sizeof(retBuf);
- err = sysctlbyname("machdep.cpu.brand_string", retBuf, &len, NULL, 0);
+ err =
+ sysctlbyname("machdep.cpu.brand_string", retBuf, &len, KWSYS_NULLPTR, 0);
if (!err) {
this->ChipID.ProcessorName = retBuf;
this->ChipID.ModelName = retBuf;
@@ -4569,10 +4584,10 @@ bool SystemInformationImplementation::ParseSysCtl()
// Cache size
len = sizeof(value);
- err = sysctlbyname("hw.l1icachesize", &value, &len, NULL, 0);
+ err = sysctlbyname("hw.l1icachesize", &value, &len, KWSYS_NULLPTR, 0);
this->Features.L1CacheSize = static_cast<int>(value);
len = sizeof(value);
- err = sysctlbyname("hw.l2cachesize", &value, &len, NULL, 0);
+ err = sysctlbyname("hw.l2cachesize", &value, &len, KWSYS_NULLPTR, 0);
this->Features.L2CacheSize = static_cast<int>(value);
return true;
@@ -4609,7 +4624,7 @@ std::string SystemInformationImplementation::RunProcess(
kwsysProcess_Execute(gp);
- char* data = NULL;
+ char* data = KWSYS_NULLPTR;
int length;
double timeout = 255;
int pipe; // pipe id as returned by kwsysProcess_WaitForData()
@@ -4621,7 +4636,7 @@ std::string SystemInformationImplementation::RunProcess(
{
buffer.append(data, length);
}
- kwsysProcess_WaitForExit(gp, 0);
+ kwsysProcess_WaitForExit(gp, KWSYS_NULLPTR);
int result = 0;
switch (kwsysProcess_GetState(gp)) {
@@ -4694,7 +4709,7 @@ std::string SystemInformationImplementation::ParseValueFromKStat(
std::string lastArg = command.substr(start + 1, command.size() - start - 1);
args.push_back(lastArg.c_str());
- args.push_back(0);
+ args.push_back(KWSYS_NULLPTR);
std::string buffer = this->RunProcess(args);
@@ -5379,7 +5394,7 @@ int SystemInformationImplementation::CallSwVers(const char* arg,
std::vector<const char*> args;
args.push_back("sw_vers");
args.push_back(arg);
- args.push_back(0);
+ args.push_back(KWSYS_NULLPTR);
ver = this->RunProcess(args);
this->TrimNewline(ver);
#else
diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in
index 516c505c5..fe7e8b557 100644
--- a/Source/kwsys/SystemInformation.hxx.in
+++ b/Source/kwsys/SystemInformation.hxx.in
@@ -103,14 +103,14 @@ public:
// Retrieve id of the current running process
LongLong GetProcessId();
- // Retrieve memory information in megabyte.
+ // Retrieve memory information in MiB.
size_t GetTotalVirtualMemory();
size_t GetAvailableVirtualMemory();
size_t GetTotalPhysicalMemory();
size_t GetAvailablePhysicalMemory();
// returns an informative general description if the installed and
- // available ram on this system. See the GetHostMmeoryTotal, and
+ // available ram on this system. See the GetHostMemoryTotal, and
// Get{Host,Proc}MemoryAvailable methods for more information.
std::string GetMemoryDescription(const char* hostLimitEnvVarName = NULL,
const char* procLimitEnvVarName = NULL);
@@ -124,7 +124,7 @@ public:
// are the processes comprising an mpi program which is running in
// parallel. The amount of memory reported may differ from the host
// total if a host wide resource limit is applied. Such reource limits
- // are reported to us via an applicaiton specified environment variable.
+ // are reported to us via an application specified environment variable.
LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL);
// Get total system RAM in units of KiB available to this process.
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index ecfa3319b..106afe507 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -20,6 +20,7 @@
#include KWSYS_HEADER(SystemTools.hxx)
#include KWSYS_HEADER(Directory.hxx)
#include KWSYS_HEADER(FStream.hxx)
+#include KWSYS_HEADER(Encoding.h)
#include KWSYS_HEADER(Encoding.hxx)
#include <fstream>
@@ -105,7 +106,8 @@ extern char** environ;
// getpwnam doesn't exist on Windows and Cray Xt3/Catamount
// same for TIOCGWINSZ
-#if defined(_WIN32) || defined(__LIBCATAMOUNT__)
+#if defined(_WIN32) || defined(__LIBCATAMOUNT__) || \
+ (defined(HAVE_GETPWNAM) && HAVE_GETPWNAM == 0)
#undef HAVE_GETPWNAM
#undef HAVE_TTY_INFO
#else
@@ -227,13 +229,17 @@ inline const char* Getcwd(char* buf, unsigned int len)
{
std::vector<wchar_t> w_buf(len);
if (_wgetcwd(&w_buf[0], len)) {
- // make sure the drive letter is capital
- if (wcslen(&w_buf[0]) > 1 && w_buf[1] == L':') {
- w_buf[0] = towupper(w_buf[0]);
+ size_t nlen = kwsysEncoding_wcstombs(buf, &w_buf[0], len);
+ if (nlen == static_cast<size_t>(-1)) {
+ return 0;
+ }
+ if (nlen < len) {
+ // make sure the drive letter is capital
+ if (nlen > 1 && buf[1] == ':') {
+ buf[0] = toupper(buf[0]);
+ }
+ return buf;
}
- std::string tmp = KWSYS_NAMESPACE::Encoding::ToNarrow(&w_buf[0]);
- strcpy(buf, tmp.c_str());
- return buf;
}
return 0;
}
@@ -300,7 +306,7 @@ inline int Chdir(const std::string& dir)
return chdir(dir.c_str());
}
inline void Realpath(const std::string& path, std::string& resolved_path,
- std::string* errorMessage = 0)
+ std::string* errorMessage = KWSYS_NULLPTR)
{
char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];
@@ -346,7 +352,7 @@ double SystemTools::GetTime(void)
11644473600.0);
#else
struct timeval t;
- gettimeofday(&t, 0);
+ gettimeofday(&t, KWSYS_NULLPTR);
return 1.0 * double(t.tv_sec) + 0.000001 * double(t.tv_usec);
#endif
}
@@ -408,7 +414,7 @@ public:
const envchar* Release(const envchar* env)
{
- const envchar* old = 0;
+ const envchar* old = KWSYS_NULLPTR;
iterator i = this->find(env);
if (i != this->end()) {
old = *i;
@@ -483,7 +489,7 @@ void SystemTools::GetPath(std::vector<std::string>& path, const char* env)
const char* SystemTools::GetEnvImpl(const char* key)
{
- const char* v = 0;
+ const char* v = KWSYS_NULLPTR;
#if defined(_WIN32)
std::string env;
if (SystemTools::GetEnv(key, env)) {
@@ -539,7 +545,7 @@ bool SystemTools::HasEnv(const char* key)
#else
const char* v = getenv(key);
#endif
- return v != 0;
+ return v != KWSYS_NULLPTR;
}
bool SystemTools::HasEnv(const std::string& key)
@@ -746,15 +752,15 @@ FILE* SystemTools::Fopen(const std::string& file, const char* mode)
#endif
}
-bool SystemTools::MakeDirectory(const char* path)
+bool SystemTools::MakeDirectory(const char* path, const mode_t* mode)
{
if (!path) {
return false;
}
- return SystemTools::MakeDirectory(std::string(path));
+ return SystemTools::MakeDirectory(std::string(path), mode);
}
-bool SystemTools::MakeDirectory(const std::string& path)
+bool SystemTools::MakeDirectory(const std::string& path, const mode_t* mode)
{
if (SystemTools::PathExists(path)) {
return SystemTools::FileIsDirectory(path);
@@ -769,8 +775,12 @@ bool SystemTools::MakeDirectory(const std::string& path)
std::string topdir;
while ((pos = dir.find('/', pos)) != std::string::npos) {
topdir = dir.substr(0, pos);
- Mkdir(topdir);
- pos++;
+
+ if (Mkdir(topdir) == 0 && mode != KWSYS_NULLPTR) {
+ SystemTools::SetPermissions(topdir, *mode);
+ }
+
+ ++pos;
}
topdir = dir;
if (Mkdir(topdir) != 0) {
@@ -785,7 +795,10 @@ bool SystemTools::MakeDirectory(const std::string& path)
) {
return false;
}
+ } else if (mode != KWSYS_NULLPTR) {
+ SystemTools::SetPermissions(topdir, *mode);
}
+
return true;
}
@@ -1059,7 +1072,7 @@ bool SystemTools::WriteRegistryValue(const std::string&, const std::string&,
// HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.1\InstallPath
// => will delete the data of the "default" value of the key
// HKEY_LOCAL_MACHINE\SOFTWARE\Scriptics\Tcl\8.4;Root
-// => will delete the data of the "Root" value of the key
+// => will delete the data of the "Root" value of the key
#if defined(_WIN32) && !defined(__CYGWIN__)
bool SystemTools::DeleteRegistryValue(const std::string& key, KeyWOW64 view)
@@ -1507,7 +1520,7 @@ char* SystemTools::AppendStrings(const char* str1, const char* str2)
size_t len1 = strlen(str1);
char* newstr = new char[len1 + strlen(str2) + 1];
if (!newstr) {
- return 0;
+ return KWSYS_NULLPTR;
}
strcpy(newstr, str1);
strcat(newstr + len1, str2);
@@ -1530,7 +1543,7 @@ char* SystemTools::AppendStrings(const char* str1, const char* str2,
size_t len1 = strlen(str1), len2 = strlen(str2);
char* newstr = new char[len1 + len2 + strlen(str3) + 1];
if (!newstr) {
- return 0;
+ return KWSYS_NULLPTR;
}
strcpy(newstr, str1);
strcat(newstr + len1, str2);
@@ -1580,7 +1593,7 @@ size_t SystemTools::CountChar(const char* str, char c)
char* SystemTools::RemoveChars(const char* str, const char* toremove)
{
if (!str) {
- return NULL;
+ return KWSYS_NULLPTR;
}
char* clean_str = new char[strlen(str) + 1];
char* ptr = clean_str;
@@ -1602,7 +1615,7 @@ char* SystemTools::RemoveChars(const char* str, const char* toremove)
char* SystemTools::RemoveCharsButUpperHex(const char* str)
{
if (!str) {
- return 0;
+ return KWSYS_NULLPTR;
}
char* clean_str = new char[strlen(str) + 1];
char* ptr = clean_str;
@@ -1679,11 +1692,11 @@ bool SystemTools::StringEndsWith(const std::string& str1, const char* str2)
: false;
}
-// Returns a pointer to the last occurence of str2 in str1
+// Returns a pointer to the last occurrence of str2 in str1
const char* SystemTools::FindLastString(const char* str1, const char* str2)
{
if (!str1 || !str2) {
- return NULL;
+ return KWSYS_NULLPTR;
}
size_t len1 = strlen(str1), len2 = strlen(str2);
@@ -1696,7 +1709,7 @@ const char* SystemTools::FindLastString(const char* str1, const char* str2)
} while (ptr-- != str1);
}
- return NULL;
+ return KWSYS_NULLPTR;
}
// Duplicate string
@@ -1706,7 +1719,7 @@ char* SystemTools::DuplicateString(const char* str)
char* newstr = new char[strlen(str) + 1];
return strcpy(newstr, str);
}
- return NULL;
+ return KWSYS_NULLPTR;
}
// Return a cropped string
@@ -1870,21 +1883,23 @@ static void ConvertVMSToUnix(std::string& path)
// convert windows slashes to unix slashes
void SystemTools::ConvertToUnixSlashes(std::string& path)
{
+ if (path.empty()) {
+ return;
+ }
+
const char* pathCString = path.c_str();
bool hasDoubleSlash = false;
#ifdef __VMS
ConvertVMSToUnix(path);
#else
const char* pos0 = pathCString;
- const char* pos1 = pathCString + 1;
for (std::string::size_type pos = 0; *pos0; ++pos) {
- // make sure we don't convert an escaped space to a unix slash
- if (*pos0 == '\\' && *pos1 != ' ') {
+ if (*pos0 == '\\') {
path[pos] = '/';
}
// Also, reuse the loop to check for slash followed by another slash
- if (*pos1 == '/' && *(pos1 + 1) == '/' && !hasDoubleSlash) {
+ if (!hasDoubleSlash && *(pos0 + 1) == '/' && *(pos0 + 2) == '/') {
#ifdef _WIN32
// However, on windows if the first characters are both slashes,
// then keep them that way, so that network paths can be handled.
@@ -1897,43 +1912,41 @@ void SystemTools::ConvertToUnixSlashes(std::string& path)
}
pos0++;
- pos1++;
}
if (hasDoubleSlash) {
SystemTools::ReplaceString(path, "//", "/");
}
#endif
+
// remove any trailing slash
- if (!path.empty()) {
- // if there is a tilda ~ then replace it with HOME
- pathCString = path.c_str();
- if (pathCString[0] == '~' &&
- (pathCString[1] == '/' || pathCString[1] == '\0')) {
- std::string homeEnv;
- if (SystemTools::GetEnv("HOME", homeEnv)) {
- path.replace(0, 1, homeEnv);
- }
+ // if there is a tilda ~ then replace it with HOME
+ pathCString = path.c_str();
+ if (pathCString[0] == '~' &&
+ (pathCString[1] == '/' || pathCString[1] == '\0')) {
+ std::string homeEnv;
+ if (SystemTools::GetEnv("HOME", homeEnv)) {
+ path.replace(0, 1, homeEnv);
}
+ }
#ifdef HAVE_GETPWNAM
- else if (pathCString[0] == '~') {
- std::string::size_type idx = path.find_first_of("/\0");
- std::string user = path.substr(1, idx - 1);
- passwd* pw = getpwnam(user.c_str());
- if (pw) {
- path.replace(0, idx, pw->pw_dir);
- }
+ else if (pathCString[0] == '~') {
+ std::string::size_type idx = path.find_first_of("/\0");
+ std::string user = path.substr(1, idx - 1);
+ passwd* pw = getpwnam(user.c_str());
+ if (pw) {
+ path.replace(0, idx, pw->pw_dir);
}
+ }
#endif
- // remove trailing slash if the path is more than
- // a single /
- pathCString = path.c_str();
- size_t size = path.size();
- if (size > 1 && *path.rbegin() == '/') {
- // if it is c:/ then do not remove the trailing slash
- if (!((size == 3 && pathCString[1] == ':'))) {
- path.resize(size - 1);
- }
+ // remove trailing slash if the path is more than
+ // a single /
+ pathCString = path.c_str();
+ size_t size = path.size();
+ if (size > 1 && *path.rbegin() == '/') {
+ // if it is c:/ then do not remove the trailing slash
+ if (!((size == 3 && pathCString[1] == ':'))) {
+ path.resize(size - 1);
}
}
}
@@ -2496,6 +2509,14 @@ bool SystemTools::RemoveFile(const std::string& source)
if (IsJunction(ws) && DeleteJunction(ws)) {
return true;
}
+ const DWORD DIRECTORY_SOFT_LINK_ATTRS =
+ FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT;
+ DWORD attrs = GetFileAttributesW(ws.c_str());
+ if (attrs != INVALID_FILE_ATTRIBUTES &&
+ (attrs & DIRECTORY_SOFT_LINK_ATTRS) == DIRECTORY_SOFT_LINK_ATTRS &&
+ RemoveDirectoryW(ws.c_str())) {
+ return true;
+ }
if (DeleteFileW(ws.c_str()) || GetLastError() == ERROR_FILE_NOT_FOUND ||
GetLastError() == ERROR_PATH_NOT_FOUND) {
return true;
@@ -3079,7 +3100,7 @@ bool SystemTools::FindProgramPath(const char* argv0, std::string& pathOut,
std::string SystemTools::CollapseFullPath(const std::string& in_relative)
{
- return SystemTools::CollapseFullPath(in_relative, 0);
+ return SystemTools::CollapseFullPath(in_relative, KWSYS_NULLPTR);
}
void SystemTools::AddTranslationPath(const std::string& a,
@@ -3149,8 +3170,8 @@ void SystemTools::CheckTranslationPath(std::string& path)
static void SystemToolsAppendComponents(
std::vector<std::string>& out_components,
- std::vector<std::string>::const_iterator first,
- std::vector<std::string>::const_iterator last)
+ std::vector<std::string>::iterator first,
+ std::vector<std::string>::iterator last)
{
static const std::string up = "..";
static const std::string cur = ".";
@@ -3160,7 +3181,11 @@ static void SystemToolsAppendComponents(
out_components.resize(out_components.size() - 1);
}
} else if (!i->empty() && *i != cur) {
+#if __cplusplus >= 201103L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201103L)
+ out_components.push_back(std::move(*i));
+#else
out_components.push_back(*i);
+#endif
}
}
}
@@ -3168,63 +3193,18 @@ static void SystemToolsAppendComponents(
std::string SystemTools::CollapseFullPath(const std::string& in_path,
const char* in_base)
{
- // Collect the output path components.
- std::vector<std::string> out_components;
-
- // Split the input path components.
- std::vector<std::string> path_components;
- SystemTools::SplitPath(in_path, path_components);
-
- // If the input path is relative, start with a base path.
- if (path_components[0].empty()) {
- std::vector<std::string> base_components;
- if (in_base) {
- // Use the given base path.
- SystemTools::SplitPath(in_base, base_components);
+ // Use the current working directory as a base path.
+ char buf[2048];
+ const char* res_in_base = in_base;
+ if (!res_in_base) {
+ if (const char* cwd = Getcwd(buf, 2048)) {
+ res_in_base = cwd;
} else {
- // Use the current working directory as a base path.
- char buf[2048];
- if (const char* cwd = Getcwd(buf, 2048)) {
- SystemTools::SplitPath(cwd, base_components);
- } else {
- base_components.push_back("");
- }
+ res_in_base = "";
}
-
- // Append base path components to the output path.
- out_components.push_back(base_components[0]);
- SystemToolsAppendComponents(out_components, base_components.begin() + 1,
- base_components.end());
}
- // Append input path components to the output path.
- SystemToolsAppendComponents(out_components, path_components.begin(),
- path_components.end());
-
- // Transform the path back to a string.
- std::string newPath = SystemTools::JoinPath(out_components);
-
- // Update the translation table with this potentially new path. I am not
- // sure why this line is here, it seems really questionable, but yet I
- // would put good money that if I remove it something will break, basically
- // from what I can see it created a mapping from the collapsed path, to be
- // replaced by the input path, which almost completely does the opposite of
- // this function, the only thing preventing this from happening a lot is
- // that if the in_path has a .. in it, then it is not added to the
- // translation table. So for most calls this either does nothing due to the
- // .. or it adds a translation between identical paths as nothing was
- // collapsed, so I am going to try to comment it out, and see what hits the
- // fan, hopefully quickly.
- // Commented out line below:
- // SystemTools::AddTranslationPath(newPath, in_path);
-
- SystemTools::CheckTranslationPath(newPath);
-#ifdef _WIN32
- newPath = SystemTools::GetActualCaseForPath(newPath);
- SystemTools::ConvertToUnixSlashes(newPath);
-#endif
- // Return the reconstructed path.
- return newPath;
+ return SystemTools::CollapseFullPath(in_path, std::string(res_in_base));
}
std::string SystemTools::CollapseFullPath(const std::string& in_path,
@@ -3236,9 +3216,10 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
// Split the input path components.
std::vector<std::string> path_components;
SystemTools::SplitPath(in_path, path_components);
+ out_components.reserve(path_components.size());
// If the input path is relative, start with a base path.
- if (path_components[0].length() == 0) {
+ if (path_components[0].empty()) {
std::vector<std::string> base_components;
// Use the given base path.
SystemTools::SplitPath(in_base, base_components);
@@ -3272,7 +3253,7 @@ std::string SystemTools::CollapseFullPath(const std::string& in_path,
SystemTools::CheckTranslationPath(newPath);
#ifdef _WIN32
- newPath = SystemTools::GetActualCaseForPath(newPath);
+ newPath = SystemTools::GetActualCaseForPathCached(newPath);
SystemTools::ConvertToUnixSlashes(newPath);
#endif
// Return the reconstructed path.
@@ -3305,7 +3286,7 @@ std::string SystemTools::RelativePath(const std::string& local,
unsigned int sameCount = 0;
while (((sameCount <= (localSplit.size() - 1)) &&
(sameCount <= (remoteSplit.size() - 1))) &&
-// for windows and apple do a case insensitive string compare
+// for Windows and Apple do a case insensitive string compare
#if defined(_WIN32) || defined(__APPLE__)
SystemTools::Strucmp(localSplit[sameCount].c_str(),
remoteSplit[sameCount].c_str()) == 0
@@ -3430,6 +3411,13 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p)
#ifndef _WIN32
return p;
#else
+ return GetCasePathName(p);
+#endif
+}
+
+#ifdef _WIN32
+std::string SystemTools::GetActualCaseForPathCached(std::string const& p)
+{
// Check to see if actual case has already been called
// for this path, and the result is stored in the PathCaseMap
SystemToolsPathCaseMap::iterator i = SystemTools::PathCaseMap->find(p);
@@ -3442,8 +3430,8 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p)
}
(*SystemTools::PathCaseMap)[p] = casePath;
return casePath;
-#endif
}
+#endif
const char* SystemTools::SplitPathRootComponent(const std::string& p,
std::string* root)
@@ -3595,7 +3583,7 @@ std::string SystemTools::JoinPath(
// All remaining components are always separated with a slash.
while (first != last) {
- result.append("/");
+ result.push_back('/');
result.append((*first++));
}
@@ -3691,7 +3679,12 @@ std::string SystemTools::GetFilenamePath(const std::string& filename)
*/
std::string SystemTools::GetFilenameName(const std::string& filename)
{
- std::string::size_type slash_pos = filename.find_last_of("/\\");
+#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
+ const char* separators = "/\\";
+#else
+ char separators = '/';
+#endif
+ std::string::size_type slash_pos = filename.find_last_of(separators);
if (slash_pos != std::string::npos) {
return filename.substr(slash_pos + 1);
} else {
@@ -4219,11 +4212,16 @@ bool SystemTools::IsSubDirectory(const std::string& cSubdir,
std::string dir = cDir;
SystemTools::ConvertToUnixSlashes(subdir);
SystemTools::ConvertToUnixSlashes(dir);
- if (subdir.size() > dir.size() && subdir[dir.size()] == '/') {
- std::string s = subdir.substr(0, dir.size());
- return SystemTools::ComparePath(s, dir);
+ if (subdir.size() <= dir.size() || dir.empty()) {
+ return false;
}
- return false;
+ bool isRootPath = *dir.rbegin() == '/'; // like "/" or "C:/"
+ size_t expectedSlashPosition = isRootPath ? dir.size() - 1u : dir.size();
+ if (subdir[expectedSlashPosition] != '/') {
+ return false;
+ }
+ std::string s = subdir.substr(0, dir.size());
+ return SystemTools::ComparePath(s, dir);
}
void SystemTools::Delay(unsigned int msec)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 35bc1b19b..e79e3fcf9 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -107,7 +107,7 @@ public:
}
/**
- * Replace replace all occurences of the string in the source string.
+ * Replace replace all occurrences of the string in the source string.
*/
static void ReplaceString(std::string& source, const char* replace,
const char* with);
@@ -175,7 +175,7 @@ public:
static bool StringEndsWith(const std::string& str1, const char* str2);
/**
- * Returns a pointer to the last occurence of str2 in str1
+ * Returns a pointer to the last occurrence of str2 in str1
*/
static const char* FindLastString(const char* str1, const char* str2);
@@ -553,13 +553,20 @@ public:
*/
static FILE* Fopen(const std::string& file, const char* mode);
+/**
+ * Visual C++ does not define mode_t (note that Borland does, however).
+ */
+#if defined(_MSC_VER)
+ typedef unsigned short mode_t;
+#endif
+
/**
* Make a new directory if it is not there. This function
* can make a full path even if none of the directories existed
* prior to calling this function.
*/
- static bool MakeDirectory(const char* path);
- static bool MakeDirectory(const std::string& path);
+ static bool MakeDirectory(const char* path, const mode_t* mode = 0);
+ static bool MakeDirectory(const std::string& path, const mode_t* mode = 0);
/**
* Copy the source file to the destination file only
@@ -749,13 +756,6 @@ public:
*/
static long int CreationTime(const std::string& filename);
-/**
- * Visual C++ does not define mode_t (note that Borland does, however).
- */
-#if defined(_MSC_VER)
- typedef unsigned short mode_t;
-#endif
-
/**
* Get and set permissions of the file. If honor_umask is set, the umask
* is queried and applied to the given permissions. Returns false if
@@ -881,7 +881,7 @@ public:
/**
* Get the width of the terminal window. The code may or may not work, so
- * make sure you have some resonable defaults prepared if the code returns
+ * make sure you have some reasonable defaults prepared if the code returns
* some bogus size.
*/
static int GetTerminalWidth();
@@ -905,7 +905,7 @@ public:
/**
* Delay the execution for a specified amount of time specified
- * in miliseconds
+ * in milliseconds
*/
static void Delay(unsigned int msec);
@@ -988,6 +988,7 @@ private:
*/
static SystemToolsTranslationMap* TranslationMap;
#ifdef _WIN32
+ static std::string GetActualCaseForPathCached(std::string const& path);
static SystemToolsPathCaseMap* PathCaseMap;
static SystemToolsEnvMap* EnvMap;
#endif
diff --git a/Source/kwsys/hash_map.hxx.in b/Source/kwsys/hash_map.hxx.in
index 3f9174f3b..8c9b81e1b 100644
--- a/Source/kwsys/hash_map.hxx.in
+++ b/Source/kwsys/hash_map.hxx.in
@@ -49,7 +49,7 @@ namespace @KWSYS_NAMESPACE@ {
// select1st is an extension: it is not part of the standard.
template <class T1, class T2>
-struct hash_select1st : public std::unary_function<std::pair<T1, T2>, T1>
+struct hash_select1st
{
const T1& operator()(const std::pair<T1, T2>& __x) const
{
diff --git a/Source/kwsys/hash_set.hxx.in b/Source/kwsys/hash_set.hxx.in
index e3a0c6c44..5edd367af 100644
--- a/Source/kwsys/hash_set.hxx.in
+++ b/Source/kwsys/hash_set.hxx.in
@@ -49,7 +49,7 @@ namespace @KWSYS_NAMESPACE@ {
// identity is an extension: it is not part of the standard.
template <class _Tp>
-struct _Identity : public std::unary_function<_Tp, _Tp>
+struct _Identity
{
const _Tp& operator()(const _Tp& __x) const { return __x; }
};
diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in
index dd92cb9d4..e962f17a9 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -35,13 +35,12 @@
#include <@KWSYS_NAMESPACE@/Configure.hxx>
-#include <algorithm> // lower_bound
-#include <functional> // unary_function
-#include <iterator> // iterator_traits
-#include <memory> // allocator
-#include <stddef.h> // size_t
-#include <utility> // pair
-#include <vector> // vector
+#include <algorithm> // lower_bound
+#include <iterator> // iterator_traits
+#include <memory> // allocator
+#include <stddef.h> // size_t
+#include <utility> // pair
+#include <vector> // vector
#if defined(_MSC_VER)
#pragma warning(push)
diff --git a/Source/kwsys/kwsysPlatformTestsC.c b/Source/kwsys/kwsysPlatformTestsC.c
index 64a361bbe..5432633eb 100644
--- a/Source/kwsys/kwsysPlatformTestsC.c
+++ b/Source/kwsys/kwsysPlatformTestsC.c
@@ -55,6 +55,21 @@ int KWSYS_PLATFORM_TEST_C_MAIN()
}
#endif
+#ifdef TEST_KWSYS_C_HAS_CLOCK_GETTIME_MONOTONIC
+#if defined(__APPLE__)
+#include <AvailabilityMacros.h>
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 101200
+#error "clock_gettime not available on macOS < 10.12"
+#endif
+#endif
+#include <time.h>
+int KWSYS_PLATFORM_TEST_C_MAIN()
+{
+ struct timespec ts;
+ return clock_gettime(CLOCK_MONOTONIC, &ts);
+}
+#endif
+
#ifdef TEST_KWSYS_C_TYPE_MACROS
char* info_macros =
#if defined(__SIZEOF_SHORT__)
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index e67d43662..f1f9ed351 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -281,7 +281,7 @@ int main()
#ifdef TEST_KWSYS_CXX_HAS_BACKTRACE
#if defined(__PATHSCALE__) || defined(__PATHCC__) || \
(defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41))
-backtrace doesnt work with this compiler or os
+backtrace does not work with this compiler or os
#endif
#if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx
index d2215d62f..78baed97a 100644
--- a/Source/kwsys/testCommandLineArguments.cxx
+++ b/Source/kwsys/testCommandLineArguments.cxx
@@ -76,7 +76,7 @@ int testCommandLineArguments(int argc, char* argv[])
int some_int_variable = 10;
double some_double_variable = 10.10;
- char* some_string_variable = 0;
+ char* some_string_variable = KWSYS_NULLPTR;
std::string some_stl_string_variable = "";
bool some_bool_variable = false;
bool some_bool_variable1 = false;
@@ -202,7 +202,7 @@ int testCommandLineArguments(int argc, char* argv[])
for (cc = 0; cc < strings_argument.size(); ++cc) {
delete[] strings_argument[cc];
- strings_argument[cc] = 0;
+ strings_argument[cc] = KWSYS_NULLPTR;
}
return res;
}
diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx
index 5a03401bc..5dfa5e3f3 100644
--- a/Source/kwsys/testCommandLineArguments1.cxx
+++ b/Source/kwsys/testCommandLineArguments1.cxx
@@ -21,7 +21,7 @@ int testCommandLineArguments1(int argc, char* argv[])
arg.Initialize(argc, argv);
int n = 0;
- char* m = 0;
+ char* m = KWSYS_NULLPTR;
std::string p;
int res = 0;
@@ -55,11 +55,11 @@ int testCommandLineArguments1(int argc, char* argv[])
delete[] m;
}
- char** newArgv = 0;
+ char** newArgv = KWSYS_NULLPTR;
int newArgc = 0;
arg.GetUnusedArguments(&newArgc, &newArgv);
int cc;
- const char* valid_unused_args[9] = { 0,
+ const char* valid_unused_args[9] = { KWSYS_NULLPTR,
"--ignored",
"--second-ignored",
"third-ignored",
diff --git a/Source/kwsys/testConfigure.cxx b/Source/kwsys/testConfigure.cxx
new file mode 100644
index 000000000..916dcc135
--- /dev/null
+++ b/Source/kwsys/testConfigure.cxx
@@ -0,0 +1,30 @@
+/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
+#include "kwsysPrivate.h"
+#include KWSYS_HEADER(Configure.hxx)
+
+// Work-around CMake dependency scanning limitation. This must
+// duplicate the above list of headers.
+#if 0
+#include "Configure.hxx.in"
+#endif
+
+static bool testFallthrough(int n)
+{
+ int r = 0;
+ switch (n) {
+ case 1:
+ ++r;
+ KWSYS_FALLTHROUGH;
+ default:
+ ++r;
+ }
+ return r == 2;
+}
+
+int testConfigure(int, char* [])
+{
+ bool res = true;
+ res = testFallthrough(1) && res;
+ return res ? 0 : 1;
+}
diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx
index 2c5ef46eb..6bf273f2c 100644
--- a/Source/kwsys/testEncoding.cxx
+++ b/Source/kwsys/testEncoding.cxx
@@ -75,12 +75,16 @@ static int testRobustEncoding()
// test that the conversion functions handle invalid
// unicode correctly/gracefully
+ // we manipulate the format flags of stdout, remember
+ // the original state here to restore before return
+ std::ios::fmtflags const& flags = std::cout.flags();
+
int ret = 0;
char cstr[] = { (char)-1, 0 };
// this conversion could fail
std::wstring wstr = kwsys::Encoding::ToWide(cstr);
- wstr = kwsys::Encoding::ToWide(NULL);
+ wstr = kwsys::Encoding::ToWide(KWSYS_NULLPTR);
if (wstr != L"") {
const wchar_t* wcstr = wstr.c_str();
std::cout << "ToWide(NULL) returned";
@@ -108,7 +112,7 @@ static int testRobustEncoding()
std::string win_str = kwsys::Encoding::ToNarrow(cwstr);
#endif
- std::string str = kwsys::Encoding::ToNarrow(NULL);
+ std::string str = kwsys::Encoding::ToNarrow(KWSYS_NULLPTR);
if (str != "") {
std::cout << "ToNarrow(NULL) returned " << str << std::endl;
ret++;
@@ -120,6 +124,7 @@ static int testRobustEncoding()
ret++;
}
+ std::cout.flags(flags);
return ret;
}
diff --git a/Source/kwsys/testProcess.c b/Source/kwsys/testProcess.c
index 092dd0347..4b4978dfe 100644
--- a/Source/kwsys/testProcess.c
+++ b/Source/kwsys/testProcess.c
@@ -107,6 +107,7 @@ static int test3(int argc, const char* argv[])
static int test4(int argc, const char* argv[])
{
+#ifndef CRASH_USING_ABORT
/* Prepare a pointer to an invalid address. Don't use null, because
dereferencing null is undefined behaviour and compilers are free to
do whatever they want. ex: Clang will warn at compile time, or even
@@ -114,6 +115,7 @@ static int test4(int argc, const char* argv[])
'volatile' and a slightly larger address, based on a runtime value. */
volatile int* invalidAddress = 0;
invalidAddress += argc ? 1 : 2;
+#endif
#if defined(_WIN32)
/* Avoid error diagnostic popups since we are crashing on purpose. */
@@ -128,9 +130,13 @@ static int test4(int argc, const char* argv[])
fprintf(stderr, "Output before crash on stderr from crash test.\n");
fflush(stdout);
fflush(stderr);
+#ifdef CRASH_USING_ABORT
+ abort();
+#else
assert(invalidAddress); /* Quiet Clang scan-build. */
/* Provoke deliberate crash by writing to the invalid address. */
*invalidAddress = 0;
+#endif
fprintf(stdout, "Output after crash on stdout from crash test.\n");
fprintf(stderr, "Output after crash on stderr from crash test.\n");
return 0;
@@ -149,7 +155,12 @@ static int test5(int argc, const char* argv[])
fprintf(stderr, "Output on stderr before recursive test.\n");
fflush(stdout);
fflush(stderr);
- r = runChild(cmd, kwsysProcess_State_Exception, kwsysProcess_Exception_Fault,
+ r = runChild(cmd, kwsysProcess_State_Exception,
+#ifdef CRASH_USING_ABORT
+ kwsysProcess_Exception_Other,
+#else
+ kwsysProcess_Exception_Fault,
+#endif
1, 1, 1, 0, 15, 0, 1, 0, 0, 0);
fprintf(stdout, "Output on stdout after recursive test.\n");
fprintf(stderr, "Output on stderr after recursive test.\n");
@@ -628,11 +639,16 @@ int main(int argc, const char* argv[])
kwsysProcess_State_Exception /* Process group test */
};
int exceptions[10] = {
- kwsysProcess_Exception_None, kwsysProcess_Exception_None,
- kwsysProcess_Exception_None, kwsysProcess_Exception_Fault,
- kwsysProcess_Exception_None, kwsysProcess_Exception_None,
- kwsysProcess_Exception_None, kwsysProcess_Exception_None,
- kwsysProcess_Exception_None, kwsysProcess_Exception_Interrupt
+ kwsysProcess_Exception_None, kwsysProcess_Exception_None,
+ kwsysProcess_Exception_None,
+#ifdef CRASH_USING_ABORT
+ kwsysProcess_Exception_Other,
+#else
+ kwsysProcess_Exception_Fault,
+#endif
+ kwsysProcess_Exception_None, kwsysProcess_Exception_None,
+ kwsysProcess_Exception_None, kwsysProcess_Exception_None,
+ kwsysProcess_Exception_None, kwsysProcess_Exception_Interrupt
};
int values[10] = { 0, 123, 1, 1, 0, 0, 0, 0, 1, 1 };
int shares[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
@@ -687,9 +703,7 @@ int main(int argc, const char* argv[])
fflush(stdout);
fflush(stderr);
#if defined(_WIN32)
- if (argv0) {
- free(argv0);
- }
+ free(argv0);
#endif
return r;
} else if (argc > 2 && strcmp(argv[1], "0") == 0) {
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 768eb4d12..e436a2b26 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -39,20 +39,20 @@ typedef unsigned short mode_t;
static const char* toUnixPaths[][2] = {
{ "/usr/local/bin/passwd", "/usr/local/bin/passwd" },
{ "/usr/lo cal/bin/pa sswd", "/usr/lo cal/bin/pa sswd" },
- { "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" },
+ { "/usr/lo\\ cal/bin/pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
{ "c:/usr/local/bin/passwd", "c:/usr/local/bin/passwd" },
{ "c:/usr/lo cal/bin/pa sswd", "c:/usr/lo cal/bin/pa sswd" },
- { "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" },
+ { "c:/usr/lo\\ cal/bin/pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
{ "\\usr\\local\\bin\\passwd", "/usr/local/bin/passwd" },
{ "\\usr\\lo cal\\bin\\pa sswd", "/usr/lo cal/bin/pa sswd" },
- { "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo\\ cal/bin/pa\\ sswd" },
+ { "\\usr\\lo\\ cal\\bin\\pa\\ sswd", "/usr/lo/ cal/bin/pa/ sswd" },
{ "c:\\usr\\local\\bin\\passwd", "c:/usr/local/bin/passwd" },
{ "c:\\usr\\lo cal\\bin\\pa sswd", "c:/usr/lo cal/bin/pa sswd" },
- { "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo\\ cal/bin/pa\\ sswd" },
+ { "c:\\usr\\lo\\ cal\\bin\\pa\\ sswd", "c:/usr/lo/ cal/bin/pa/ sswd" },
{ "\\\\usr\\local\\bin\\passwd", "//usr/local/bin/passwd" },
{ "\\\\usr\\lo cal\\bin\\pa sswd", "//usr/lo cal/bin/pa sswd" },
- { "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo\\ cal/bin/pa\\ sswd" },
- { 0, 0 }
+ { "\\\\usr\\lo\\ cal\\bin\\pa\\ sswd", "//usr/lo/ cal/bin/pa/ sswd" },
+ { KWSYS_NULLPTR, KWSYS_NULLPTR }
};
static bool CheckConvertToUnixSlashes(std::string const& input,
@@ -68,10 +68,11 @@ static bool CheckConvertToUnixSlashes(std::string const& input,
return true;
}
-static const char* checkEscapeChars[][4] = { { "1 foo 2 bar 2", "12", "\\",
- "\\1 foo \\2 bar \\2" },
- { " {} ", "{}", "#", " #{#} " },
- { 0, 0, 0, 0 } };
+static const char* checkEscapeChars[][4] = {
+ { "1 foo 2 bar 2", "12", "\\", "\\1 foo \\2 bar \\2" },
+ { " {} ", "{}", "#", " #{#} " },
+ { KWSYS_NULLPTR, KWSYS_NULLPTR, KWSYS_NULLPTR, KWSYS_NULLPTR }
+};
static bool CheckEscapeChars(std::string const& input,
const char* chars_to_escape, char escape_char,
@@ -159,7 +160,7 @@ static bool CheckFileOperations()
res = false;
}
// calling with 0 pointer should return false
- if (kwsys::SystemTools::MakeDirectory(0)) {
+ if (kwsys::SystemTools::MakeDirectory(KWSYS_NULLPTR)) {
std::cerr << "Problem with MakeDirectory(0)" << std::endl;
res = false;
}
@@ -217,11 +218,11 @@ static bool CheckFileOperations()
}
// calling with 0 pointer should return false
- if (kwsys::SystemTools::FileExists(0)) {
+ if (kwsys::SystemTools::FileExists(KWSYS_NULLPTR)) {
std::cerr << "Problem with FileExists(0)" << std::endl;
res = false;
}
- if (kwsys::SystemTools::FileExists(0, true)) {
+ if (kwsys::SystemTools::FileExists(KWSYS_NULLPTR, true)) {
std::cerr << "Problem with FileExists(0) as file" << std::endl;
res = false;
}
@@ -254,22 +255,22 @@ static bool CheckFileOperations()
}
// should work, was created as new file before
if (!kwsys::SystemTools::FileExists(testNewFile)) {
- std::cerr << "Problem with FileExists for: " << testNewDir << std::endl;
+ std::cerr << "Problem with FileExists for: " << testNewFile << std::endl;
res = false;
}
if (!kwsys::SystemTools::FileExists(testNewFile.c_str())) {
- std::cerr << "Problem with FileExists as C string for: " << testNewDir
+ std::cerr << "Problem with FileExists as C string for: " << testNewFile
<< std::endl;
res = false;
}
if (!kwsys::SystemTools::FileExists(testNewFile, true)) {
- std::cerr << "Problem with FileExists as file for: " << testNewDir
+ std::cerr << "Problem with FileExists as file for: " << testNewFile
<< std::endl;
res = false;
}
if (!kwsys::SystemTools::FileExists(testNewFile.c_str(), true)) {
std::cerr << "Problem with FileExists as C string and file for: "
- << testNewDir << std::endl;
+ << testNewFile << std::endl;
res = false;
}
@@ -285,7 +286,7 @@ static bool CheckFileOperations()
}
// should work, was created as new file before
if (!kwsys::SystemTools::PathExists(testNewFile)) {
- std::cerr << "Problem with PathExists for: " << testNewDir << std::endl;
+ std::cerr << "Problem with PathExists for: " << testNewFile << std::endl;
res = false;
}
@@ -699,6 +700,16 @@ static bool CheckCollapsePath()
bool res = true;
res &= CheckCollapsePath("/usr/share/*", "/usr/share/*");
res &= CheckCollapsePath("C:/Windows/*", "C:/Windows/*");
+ res &= CheckCollapsePath("/usr/share/../lib", "/usr/lib");
+ res &= CheckCollapsePath("/usr/share/./lib", "/usr/share/lib");
+ res &= CheckCollapsePath("/usr/share/../../lib", "/lib");
+ res &= CheckCollapsePath("/usr/share/.././../lib", "/lib");
+ res &= CheckCollapsePath("/../lib", "/lib");
+ res &= CheckCollapsePath("/../lib/", "/lib");
+ res &= CheckCollapsePath("/", "/");
+ res &= CheckCollapsePath("C:/", "C:/");
+ res &= CheckCollapsePath("C:/../", "C:/");
+ res &= CheckCollapsePath("C:/../../", "C:/");
return res;
}
@@ -763,20 +774,26 @@ static bool CheckGetFilenameName()
const char* windowsFilepath = "C:\\somewhere\\something";
const char* unixFilepath = "/somewhere/something";
- std::string expectedFilename = "something";
+#if defined(_WIN32) || defined(KWSYS_SYSTEMTOOLS_SUPPORT_WINDOWS_SLASHES)
+ std::string expectedWindowsFilename = "something";
+#else
+ std::string expectedWindowsFilename = "C:\\somewhere\\something";
+#endif
+ std::string expectedUnixFilename = "something";
bool res = true;
std::string filename = kwsys::SystemTools::GetFilenameName(windowsFilepath);
- if (filename != expectedFilename) {
+ if (filename != expectedWindowsFilename) {
std::cerr << "GetFilenameName(" << windowsFilepath << ") yielded "
- << filename << " instead of " << expectedFilename << std::endl;
+ << filename << " instead of " << expectedWindowsFilename
+ << std::endl;
res = false;
}
filename = kwsys::SystemTools::GetFilenameName(unixFilepath);
- if (filename != expectedFilename) {
+ if (filename != expectedUnixFilename) {
std::cerr << "GetFilenameName(" << unixFilepath << ") yielded " << filename
- << " instead of " << expectedFilename << std::endl;
+ << " instead of " << expectedUnixFilename << std::endl;
res = false;
}
return res;
@@ -813,6 +830,39 @@ static bool CheckFind()
return res;
}
+static bool CheckIsSubDirectory()
+{
+ bool res = true;
+
+ if (kwsys::SystemTools::IsSubDirectory("/foo", "/") == false) {
+ std::cerr << "Problem with IsSubDirectory (root - unix): " << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::IsSubDirectory("c:/foo", "c:/") == false) {
+ std::cerr << "Problem with IsSubDirectory (root - dos): " << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::IsSubDirectory("/foo/bar", "/foo") == false) {
+ std::cerr << "Problem with IsSubDirectory (deep): " << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::IsSubDirectory("/foo", "/foo") == true) {
+ std::cerr << "Problem with IsSubDirectory (identity): " << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::IsSubDirectory("/fooo", "/foo") == true) {
+ std::cerr << "Problem with IsSubDirectory (substring): " << std::endl;
+ res = false;
+ }
+ if (kwsys::SystemTools::IsSubDirectory("/foo/", "/foo") == true) {
+ std::cerr << "Problem with IsSubDirectory (prepended slash): "
+ << std::endl;
+ res = false;
+ }
+
+ return res;
+}
+
static bool CheckGetLineFromStream()
{
const std::string fileWithFiveCharsOnFirstLine(TEST_SYSTEMTOOLS_SOURCE_DIR
@@ -897,6 +947,8 @@ int testSystemTools(int, char* [])
res &= CheckFind();
+ res &= CheckIsSubDirectory();
+
res &= CheckGetLineFromStream();
res &= CheckGetFilenameName();